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