Mstdlib-1.24.0
m_list_u64.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_LIST_U64_H__
25#define __M_LIST_U64_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31
32/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
33
34__BEGIN_DECLS
35
36/*! \addtogroup m_list_u64 List - uint64
37 * \ingroup m_list
38 *
39 * Dynamic list (array) for storing unsigned 64 bit integer values.
40 *
41 * The list can be used in multiple ways:
42 * - Unsorted.
43 * - Sorted.
44 * - Queue (FIFO) (really just unsorted).
45 * - Stack (LIFO) (which cannot be sorted).
46 * - Set.
47 *
48 * A list is indexable. Find is also supported.
49 *
50 * Indexes in the list are 0 at head to len-1 at end (head ... end).
51 * Functions like M_list_first will return head and M_list_last will return end.
52 *
53 * The index start changes in STACK mode. In STACK mode indexing is opposite.
54 * Head is len-1 and end is 0 (head ... end). Entries are still added to end.
55 * Functions like M_list_first will return end and M_list_last will return head.
56 * This is to accommodate STACKS where entries are inserted and removed from
57 * the same end.
58 *
59 * The list is designed for efficient head removal. A value removed from head
60 * will not cause a memmove. Instead a start offset will be noted. If there is
61 * space before head (due to removals) then additions at head will be efficient
62 * as the empty space will be used and a memmove will be avoided. memmoves
63 * will occur when the size (not necessarly number of elements) of the list
64 * changes (expand and shink) and for removals in the middle of the list.
65 *
66 * Sorted notes:
67 * - Sorting on insert and find (M_list_u64_index_of()) is done using binary insert/search.
68 * - When M_list_insert_end() is called after M_list_insert_begin() qsort will be
69 * used to sort the list.
70 *
71 * @{
72 */
73
74struct M_list_u64;
75/* Currently a direct map to M_list private opaque type,
76 * simply using casting to prevent the 'wrap' overhead of mallocing when it
77 * is not necessary */
78typedef struct M_list_u64 M_list_u64_t;
79
80/*! Flags for controlling the behavior of the list. */
81typedef enum {
82 M_LIST_U64_NONE = 1 << 0, /*!< Not sorting, asc compare. */
83 M_LIST_U64_SORTASC = 1 << 1, /*!< Sort asc. */
84 M_LIST_U64_SORTDESC = 1 << 2, /*!< Sort desc. */
85 M_LIST_U64_STABLE = 1 << 3, /*!< Make insert, search and sort stable. */
86 M_LIST_U64_STACK = 1 << 4, /*!< Last in First out mode. */
87 M_LIST_U64_SET = 1 << 5, /*!< Don't allow duplicates in the list.
88 Insert is increased by an additional O(n) operation (on top of the insert
89 itself) in order to determine if a value is a duplicate for unsorted.
90 Insert is increased by an additional O(log(n)) operation (on top of the
91 insert itself) in order to determine if a value is a duplicate for sorted. */
92 M_LIST_U64_NEVERSHRINK = 1 << 6 /*!< Never allow the list to shrink. */
94
95
96/*! Type of matching that should be used when searching/modifying a value in the list. */
97typedef enum {
98 M_LIST_U64_MATCH_VAL = 0, /*!< Match based on the value (equality function). */
99 M_LIST_U64_MATCH_ALL = 1 << 0 /*!< Include all instances. */
101
102
103/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
104
105/*! Create a new dynamic list.
106 *
107 * A dynamic list is a dynamically expanding array. Meaning the array will expand to accommodate new elements.
108 * The list can be, optionally, kept in sorted order.
109 *
110 * \param[in] flags M_list_u64_flags_t flags for controlling behavior.
111 *
112 * \return Allocated dynamic list for storing strings.
113 *
114 * \see M_list_u64_destroy
115 */
116M_API M_list_u64_t *M_list_u64_create(M_uint32 flags) M_MALLOC;
117
118
119/*! Destory the list.
120 *
121 * \param[in] d The list to destory.
122 */
123M_API void M_list_u64_destroy(M_list_u64_t *d) M_FREE(1);
124
125
126/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
127
128/*! Change the sorting behavior of the list.
129 *
130 * \param[in,out] d The list.
131 * \param[in] flags M_list_u64_flags_t flags that control sorting.
132 */
133M_API void M_list_u64_change_sorting(M_list_u64_t *d, M_uint32 flags);
134
135
136/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
137
138/*! Insert a value into the list.
139 *
140 * If sorted the value will be inserted in sorted order. Otherwise it will be
141 * appended to the end of the list.
142 *
143 * \param[in,out] d The list.
144 * \param[in] val The value to insert.
145 *
146 * \return M_TRUE on success otherwise M_FALSE.
147 */
148M_API M_bool M_list_u64_insert(M_list_u64_t *d, M_uint64 val);
149
150
151/*! Get the index a value would be insert into the list at.
152 *
153 * This does not actually insert the value into the list it only gets the position the value would
154 * be insert into the list if/when insert is called.
155 *
156 * \param[in] d The list.
157 * \param[in] val The value to get the insertion index for.
158 *
159 * \return The insertion index.
160 */
161M_API size_t M_list_u64_insert_idx(const M_list_u64_t *d, M_uint64 *val);
162
163
164/*! Insert a value into the list at a specific position.
165 *
166 * This is only supported for non-sorted lists.
167 *
168 * \param[in,out] d The list.
169 * \param[in] val The value to insert.
170 * \param[in] idx The position to insert at. An index larger than the number of
171 * elements in the list will result in the item being inserted
172 * at the end.
173 *
174 * \return M_TRUE on success otherwise M_FALSE.
175 */
176M_API M_bool M_list_u64_insert_at(M_list_u64_t *d, M_uint64 val, size_t idx);
177
178
179/*! Start a grouped insertion.
180 *
181 * This is only useful for sorted lists. This will defer sorting until
182 * M_list_u64_insert_end() is called. This is to allow many items to be inserted
183 * at once without the sorting overhead being called for every insertion.
184 *
185 * \param[in,out] d The list.
186 *
187 * \see M_list_u64_insert_end
188 */
190
191
192/*! End a grouped insertion.
193 *
194 * This is only useful for sorted lists. Cause all elements in the list (if
195 * sorting is enabled) to be sorted.
196 *
197 * \param[in,out] d The list.
198 *
199 * \see M_list_u64_insert_begin
200 */
202
203
204/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
205
206/*! The length of the list.
207 *
208 * \param[in] d The list.
209 *
210 * \return the length of the list.
211 */
212M_API size_t M_list_u64_len(const M_list_u64_t *d);
213
214
215/*! Count the number of times a value occurs in the list.
216 *
217 * \param[in] d The list.
218 * \param[in] val The value to search for.
219 *
220 * \return The number of times val appears in the list.
221 */
222M_API size_t M_list_u64_count(const M_list_u64_t *d, M_uint64 val);
223
224
225/*! Get the location of a value within the list.
226 *
227 * This will return a location in the list which may not be the first occurrence in the list.
228 *
229 * \param[in] d The list.
230 * \param[in] val The value to search for.
231 * \param[out] idx The index of the value within the list. Optional, pass NULL if not needed.
232 *
233 * \return M_TRUE if the value was found within the list. Otherwise M_FALSE.
234 */
235M_API M_bool M_list_u64_index_of(const M_list_u64_t *d, M_uint64 val, size_t *idx);
236
237
238/*! Get the first element.
239 *
240 * The element will remain a member of the list.
241 *
242 * \param[in] d The list.
243 *
244 * \return The element or NULL if there are no elements.
245 *
246 * \see M_list_u64_at
247 * \see M_list_u64_last
248 */
249M_API M_uint64 M_list_u64_first(const M_list_u64_t *d);
250
251
252/*! Get the last element.
253 *
254 * The element will remain a member of the list.
255 *
256 * \param[in] d The list.
257 *
258 * \return The element or NULL if there are no elements.
259 *
260 * \see M_list_at
261 * \see M_list_first
262 */
263M_API M_uint64 M_list_u64_last(const M_list_u64_t *d);
264
265
266/*! Get the element at a given index.
267 *
268 * The element will remain a member of the list.
269 *
270 * \param[in] d The list.
271 * \param[in] idx The location to retrieve the element from.
272 *
273 * \return The element or NULL if index is out range.
274 *
275 * \see M_list_u64_first
276 * \see M_list_u64_last
277 */
278M_API M_uint64 M_list_u64_at(const M_list_u64_t *d, size_t idx);
279
280
281/*! Take the first element.
282 *
283 * The element will be removed from the list and returned. The caller is
284 * responsible for freeing the element.
285 *
286 * \param[in,out] d The list.
287 *
288 * \return The element or NULL if there are no elements.
289 *
290 * \see M_list_u64_take_at
291 * \see M_list_u64_last
292 */
294
295
296/*! Take the last element.
297 *
298 * The element will be removed from the list and returned. The caller is
299 * responsible for freeing the element.
300 *
301 * \param[in,out] d The list.
302 *
303 * \return The element or NULL if there are no elements.
304 *
305 * \see M_list_u64_take_at
306 * \see M_list_u64_take_first
307 */
309
310
311/*! Take the element at a given index.
312 *
313 * The element will be removed from the list and returned. The caller is
314 * responsible for freeing the element.
315 *
316 * \param[in,out] d The list.
317 * \param[in] idx The location to retrieve the element from.
318 *
319 * \return The element or NULL if index is out range.
320 *
321 * \see M_list_u64_take_first
322 * \see M_list_u64_take_last
323 */
324M_API M_uint64 M_list_u64_take_at(M_list_u64_t *d, size_t idx);
325
326
327/*! Remove the first element.
328 *
329 * \param[in,out] d The list.
330 *
331 * \return M_TRUE if the element was removed. Otherwise M_FALSE.
332 *
333 * \see M_list_u64_remove_at
334 * \see M_list_u64_remove_last
335 */
337
338
339/*! Remove the last element.
340 *
341 * \param[in,out] d The list.
342 *
343 * \return M_TRUE if the element was removed. Otherwise M_FALSE.
344 *
345 * \see M_list_u64_remove_at
346 * \see M_list_u64_remove_first
347 */
349
350
351/*! Remove an element at a given index from the list.
352 *
353 * \param[in,out] d The list.
354 * \param[in] idx The index to remove.
355 *
356 * \return M_TRUE if the element was removed. Otherwise M_FALSE.
357 *
358 * \ see M_list_u64_remove_first
359 * \ see M_list_u64_remove_last
360 * \ see M_list_u64_remove_val
361 * \ see M_list_u64_remove_range
362 */
363M_API M_bool M_list_u64_remove_at(M_list_u64_t *d, size_t idx);
364
365
366/*! Remove element(s) from the list.
367 *
368 * Searches the list for the occurrence of val and removes it from the
369 * list.
370 *
371 * \param[in,out] d The list.
372 * \param[in] val The val to remove
373 * \param[in] type M_list_u64_match_type_t type of how the val should be matched.
374 *
375 * \return The number of elements removed.
376 *
377 * \see M_list_u64_remove_at
378 */
379M_API size_t M_list_u64_remove_val(M_list_u64_t *d, M_uint64 val, M_uint32 type);
380
381
382/*! Remove a range of elements form the list.
383 *
384 * \param[in,out] d The list.
385 * \param[in] start The start index. Inclusive.
386 * \param[in] end The end index. Inclusive.
387 *
388 * \return M_TRUE if the range was removed. Otherwise M_FALSE.
389 */
390M_API M_bool M_list_u64_remove_range(M_list_u64_t *d, size_t start, size_t end);
391
392
393/*! Remove duplicate elements from the list.
394 *
395 * \param[in] d The list.
396 */
398
399
400/*! Replace all matching values in the list with a different value.
401 *
402 * \param[in,out] d The list.
403 * \param[in] val The val to be replaced.
404 * \param[in] new_val The value to be replaced with.
405 * \param[in] type M_list_u64_match_type_t type of how the val should be matched.
406 *
407 * \return The number of elements replaced.
408 */
409M_API size_t M_list_u64_replace_val(M_list_u64_t *d, M_uint64 val, M_uint64 new_val, M_uint32 type);
410
411
412/*! Replace a value in the list with a different value.
413 *
414 * \param[in,out] d The list.
415 * \param[in] val The val to that will appear in the list at the given idx.
416 * \param[in] idx The index to replace.
417 *
418 * \return M_TRUE if the value was replaced. Otherwise M_FALSE.
419 */
420M_API M_bool M_list_u64_replace_at(M_list_u64_t *d, M_uint64 val, size_t idx);
421
422
423/*! Exchange the elements at the given locations.
424 *
425 * This only applies to unsorted lists.
426 *
427 * \param[in,out] d The list.
428 * \param[in] idx1 The first index.
429 * \param[in] idx2 The second index.
430 *
431 * \return M_TRUE if the elements were swapped.
432 */
433M_API M_bool M_list_u64_swap(M_list_u64_t *d, size_t idx1, size_t idx2);
434
435
436/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
437
438/*! Duplicate an existing list.
439 *
440 * Will copy all elements of the list as well as any flags, etc.
441 *
442 * \param[in] d list to duplicate.
443 *
444 * \return New list.
445 */
447
448
449/*! Merge two lists together.
450 *
451 * The second (src) list will be destroyed automatically upon completion of this function. Any value pointers for the
452 * list will be directly copied over to the destination list, they will not be duplicated.
453 *
454 * \param[in,out] dest Pointer by reference to the list receiving the values.
455 * if this is NULL, the pointer will simply be switched out for src.
456 * \param[in,out] src Pointer to the list giving up its values.
457 * \param[in] include_duplicates When M_TRUE any values in 'dest' that also exist in
458 * 'src' will be included in 'dest'. When M_FALSE any
459 * duplicate values will not be added to 'dest'.
460 */
461M_API void M_list_u64_merge(M_list_u64_t **dest, M_list_u64_t *src, M_bool include_duplicates) M_FREE(2);
462
463/*! @} */
464
465__END_DECLS
466
467#endif /* __M_LIST_U64_H__ */
M_bool M_list_u64_remove_range(M_list_u64_t *d, size_t start, size_t end)
M_list_u64_t * M_list_u64_duplicate(const M_list_u64_t *d) M_MALLOC
M_uint64 M_list_u64_last(const M_list_u64_t *d)
M_uint64 M_list_u64_at(const M_list_u64_t *d, size_t idx)
M_bool M_list_u64_remove_last(M_list_u64_t *d)
M_bool M_list_u64_remove_at(M_list_u64_t *d, size_t idx)
void M_list_u64_insert_end(M_list_u64_t *d)
M_bool M_list_u64_replace_at(M_list_u64_t *d, M_uint64 val, size_t idx)
M_uint64 M_list_u64_take_at(M_list_u64_t *d, size_t idx)
M_bool M_list_u64_insert_at(M_list_u64_t *d, M_uint64 val, size_t idx)
void M_list_u64_merge(M_list_u64_t **dest, M_list_u64_t *src, M_bool include_duplicates) M_FREE(2)
M_bool M_list_u64_insert(M_list_u64_t *d, M_uint64 val)
struct M_list_u64 M_list_u64_t
Definition: m_list_u64.h:78
void M_list_u64_destroy(M_list_u64_t *d) M_FREE(1)
M_list_u64_t * M_list_u64_create(M_uint32 flags) M_MALLOC
M_bool M_list_u64_remove_first(M_list_u64_t *d)
M_bool M_list_u64_index_of(const M_list_u64_t *d, M_uint64 val, size_t *idx)
M_uint64 M_list_u64_take_first(M_list_u64_t *d)
void M_list_u64_insert_begin(M_list_u64_t *d)
M_list_u64_match_type_t
Definition: m_list_u64.h:97
size_t M_list_u64_replace_val(M_list_u64_t *d, M_uint64 val, M_uint64 new_val, M_uint32 type)
size_t M_list_u64_insert_idx(const M_list_u64_t *d, M_uint64 *val)
M_bool M_list_u64_swap(M_list_u64_t *d, size_t idx1, size_t idx2)
void M_list_u64_change_sorting(M_list_u64_t *d, M_uint32 flags)
M_uint64 M_list_u64_take_last(M_list_u64_t *d)
size_t M_list_u64_remove_val(M_list_u64_t *d, M_uint64 val, M_uint32 type)
size_t M_list_u64_count(const M_list_u64_t *d, M_uint64 val)
size_t M_list_u64_len(const M_list_u64_t *d)
M_uint64 M_list_u64_first(const M_list_u64_t *d)
void M_list_u64_remove_duplicates(M_list_u64_t *d)
M_list_u64_flags_t
Definition: m_list_u64.h:81
@ M_LIST_U64_MATCH_VAL
Definition: m_list_u64.h:98
@ M_LIST_U64_MATCH_ALL
Definition: m_list_u64.h:99
@ M_LIST_U64_NONE
Definition: m_list_u64.h:82
@ M_LIST_U64_NEVERSHRINK
Definition: m_list_u64.h:92
@ M_LIST_U64_STACK
Definition: m_list_u64.h:86
@ M_LIST_U64_SET
Definition: m_list_u64.h:87
@ M_LIST_U64_SORTDESC
Definition: m_list_u64.h:84
@ M_LIST_U64_STABLE
Definition: m_list_u64.h:85
@ M_LIST_U64_SORTASC
Definition: m_list_u64.h:83