/src/core/libntech/libutils/sequence.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright 2023 Northern.tech AS |
3 | | |
4 | | This file is part of CFEngine 3 - written and maintained by Northern.tech AS. |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify it |
7 | | under the terms of the GNU General Public License as published by the |
8 | | Free Software Foundation; version 3. |
9 | | |
10 | | This program is distributed in the hope that it will be useful, |
11 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | GNU General Public License for more details. |
14 | | |
15 | | You should have received a copy of the GNU General Public License |
16 | | along with this program; if not, write to the Free Software |
17 | | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
18 | | |
19 | | To the extent this program is licensed as part of the Enterprise |
20 | | versions of CFEngine, the applicable Commercial Open Source License |
21 | | (COSL) may apply to this file if you as a licensee so wish it. See |
22 | | included file COSL.txt. |
23 | | */ |
24 | | |
25 | | #ifndef CFENGINE_SEQUENCE_H |
26 | | #define CFENGINE_SEQUENCE_H |
27 | | |
28 | | #include <stddef.h> // size_t |
29 | | #include <sys/types.h> // ssize_t |
30 | | #include <assert.h> // assert() |
31 | | #include <stdio.h> // FILE |
32 | | |
33 | | /** |
34 | | @brief Sequence data-structure. |
35 | | |
36 | | This is an array-list loosely modeled on GSequence. It is a managed array of |
37 | | void pointers and can be used to store arbitrary data. The array list will |
38 | | auto-expand by a factor of EXPAND_FACTOR (e.g. 2) when necessary, but not |
39 | | contract. Because sequence is content agnostic, it does not support the |
40 | | usual copy semantics found in other CFEngine structures, such as |
41 | | RList. Thus, appending an item to a Sequence may imply a transfer of |
42 | | ownership. Clients that require copy semantics should therefore make sure |
43 | | that elements are copied before they are appended. Some Sequence operations |
44 | | may remove some or all of the elements held. In order to do so safely, it's |
45 | | incumbent upon the client to supply the necessary item destructor to the |
46 | | Sequence constructor. If the item destructor argument is NULL, Sequence will |
47 | | not attempt to free the item memory held. |
48 | | */ |
49 | | typedef struct |
50 | | { |
51 | | void **data; |
52 | | size_t length; |
53 | | size_t capacity; |
54 | | void (*ItemDestroy) (void *item); |
55 | | } Seq; |
56 | | |
57 | | static inline void *SeqAt(const Seq *seq, size_t i) |
58 | 0 | { |
59 | 0 | assert(seq != NULL); |
60 | 0 | assert(i < seq->length); |
61 | 0 | return seq->data[i]; |
62 | 0 | } Unexecuted instantiation: misc_lib.c:SeqAt Unexecuted instantiation: logging.c:SeqAt Unexecuted instantiation: sequence.c:SeqAt Unexecuted instantiation: string_lib.c:SeqAt |
63 | | |
64 | | /** |
65 | | @brief Length of the sequence. |
66 | | @note On NULL sequence return size 0. |
67 | | @param seq [in] sequence. |
68 | | @return Sequence length. |
69 | | */ |
70 | | size_t SeqLength(const Seq *seq); |
71 | | |
72 | | /** |
73 | | @brief Create a new Sequence |
74 | | @param [in] initial_capacity Size of initial buffer to allocate for item pointers. |
75 | | @param [in] ItemDestroy Optional item destructor to clean up memory when needed. |
76 | | @return A pointer to the created Sequence |
77 | | */ |
78 | | Seq *SeqNew(size_t initial_capacity, void (*ItemDestroy) ()); |
79 | | |
80 | | /** |
81 | | @brief Destroy an existing Sequence |
82 | | @param [in] seq The Sequence to destroy. |
83 | | */ |
84 | | void SeqDestroy(Seq *seq); |
85 | | |
86 | | /** |
87 | | @brief Destroy an existing Sequence without destroying its items. |
88 | | @param [in] seq The Sequence to destroy. |
89 | | */ |
90 | | void SeqSoftDestroy(Seq *seq); |
91 | | |
92 | | /** |
93 | | @brief |
94 | | Function to compare two items in a Sequence. |
95 | | |
96 | | @retval -1 if the first argument is smaller than the second |
97 | | @retval 0 if the arguments are equal |
98 | | @retval 1 if the first argument is bigger than the second |
99 | | */ |
100 | | typedef int (*SeqItemComparator) (const void *, const void *, void *user_data); |
101 | | |
102 | | /** |
103 | | @brief Wrapper of the standard library function strcmp. |
104 | | Used to avoid cast-function-type compiler warnings when |
105 | | casting strcmp to (SeqItemComparator) in sequence functions. |
106 | | |
107 | | @param [in] s1 The string being compared to the s2 string |
108 | | @param [in] s2 The string that s1 is compared to |
109 | | @param [in] user_data This parameter is the ignored user_data that the SeqItemComparator |
110 | | expects |
111 | | |
112 | | @return 0 if s1 and s2 strings are equal |
113 | | @return negative if s1 is less than s2 |
114 | | @return positive if s1 is greater than s2 |
115 | | */ |
116 | | int StrCmpWrapper(const void *s1, const void *s2, void *user_data); |
117 | | |
118 | | /** |
119 | | * Replace value at #index. |
120 | | * |
121 | | * @warning Destroys the original item at #index! See SeqSoftSet(). |
122 | | */ |
123 | | void SeqSet(Seq *set, size_t index, void *item); |
124 | | |
125 | | /** |
126 | | * Set value at #index. |
127 | | * |
128 | | * @note Make sure the original item at #index is destroyed. |
129 | | */ |
130 | | void SeqSoftSet(Seq *set, size_t index, void *item); |
131 | | |
132 | | /** |
133 | | @brief Append a new item to the Sequence |
134 | | @param seq [in] The Sequence to append to. |
135 | | @param item [in] The item to append. Note that this item may be passed to the item destructor specified in the constructor. |
136 | | */ |
137 | | void SeqAppend(Seq *seq, void *item); |
138 | | |
139 | | /** |
140 | | @brief Append a new item to the Sequence if it's not already present in the Sequence. |
141 | | @note This calls SeqLookup() and thus linearly searches through the sequence. |
142 | | @param seq [in] The Sequence to append to. |
143 | | @param item [in] The item to append. Note that this item will be passed to the item destructor specified in the constructor. |
144 | | Either immediately if the same item (according to Compare()) is found in the Sequence or once the Sequence |
145 | | is destroyed with SeqDestroy(). |
146 | | */ |
147 | | void SeqAppendOnce(Seq *seq, void *item, SeqItemComparator Compare); |
148 | | |
149 | | /** |
150 | | * @brief Append a sequence to this sequence. Only copies pointers. |
151 | | * @param seq Sequence to append to |
152 | | * @param items Sequence to copy pointers from. |
153 | | */ |
154 | | void SeqAppendSeq(Seq *seq, const Seq *items); |
155 | | |
156 | | /** |
157 | | @brief Linearly searches through the sequence and return the first item considered equal to the specified key. |
158 | | @param seq [in] The Sequence to search. |
159 | | @param key [in] The item to compare against. |
160 | | @param compare [in] Comparator function to use. An item matches if the function returns 0. |
161 | | @returns A pointer to the found item, or NULL if not found. |
162 | | */ |
163 | | void *SeqLookup(Seq *seq, const void *key, SeqItemComparator Compare); |
164 | | |
165 | | /** |
166 | | * @brief Performs a binary search looking for the item matching the given key. |
167 | | * It is the programmer's responsibility to make sure that the sequence is already sorted. |
168 | | * @param seq [in] The Sequence to search. |
169 | | * @param key [in] The item to compare against. |
170 | | * @param compare [in] Comparator function to use (return value has strcmp semantics). |
171 | | * @returns A pointer to the found item, or NULL if not found. |
172 | | */ |
173 | | void *SeqBinaryLookup(Seq *seq, const void *key, SeqItemComparator Compare); |
174 | | |
175 | | /** |
176 | | @brief Linearly searches through the sequence and returns the index of the first matching object, or -1 if it doesn't exist. |
177 | | */ |
178 | | ssize_t SeqIndexOf(Seq *seq, const void *key, SeqItemComparator Compare); |
179 | | |
180 | | /** |
181 | | * @brief Performs a binary search looking for the item matching the given key. |
182 | | * It is the programmer's responsibility to make sure that the sequence is already sorted. |
183 | | * @param seq [in] The Sequence to search. |
184 | | * @param key [in] The item to compare against. |
185 | | * @param compare [in] Comparator function to use (return value has strcmp semantics). |
186 | | * @returns The index of the item, or -1 if it is not found. |
187 | | */ |
188 | | ssize_t SeqBinaryIndexOf(Seq *seq, const void *key, SeqItemComparator Compare); |
189 | | |
190 | | /** |
191 | | @brief Remove an inclusive range of items in the Sequence. A single item may be removed by specifying start = end. |
192 | | @param seq [in] The Sequence to remove from. |
193 | | @param start [in] Index of the first element to remove |
194 | | @param end [in] Index of the last element to remove. |
195 | | */ |
196 | | void SeqRemoveRange(Seq *seq, size_t start, size_t end); |
197 | | |
198 | | /** |
199 | | @brief Remove a single item in the sequence |
200 | | */ |
201 | | void SeqRemove(Seq *seq, size_t index); |
202 | | |
203 | | /** |
204 | | @brief Sort a Sequence according to the given item comparator function |
205 | | @param compare [in] The comparator function used for sorting. |
206 | | @param user_data [in] Pointer passed to the comparator function |
207 | | */ |
208 | | void SeqSort(Seq *seq, SeqItemComparator compare, void *user_data); |
209 | | |
210 | | /** |
211 | | @brief Returns a soft copy of the sequence sorted according to the given item comparator function. |
212 | | @param compare [in] The comparator function used for sorting. |
213 | | @param user_data [in] Pointer passed to the comparator function |
214 | | */ |
215 | | Seq *SeqSoftSort(const Seq *seq, SeqItemComparator compare, void *user_data); |
216 | | |
217 | | /** |
218 | | @brief Remove an inclusive range of item handles in the Sequence. A single item may be removed by specifying start = end. |
219 | | @param seq [in] The Sequence to remove from. |
220 | | @param start [in] Index of the first element to remove |
221 | | @param end [in] Index of the last element to remove. |
222 | | */ |
223 | | void SeqSoftRemoveRange(Seq *seq, size_t start, size_t end); |
224 | | |
225 | | /** |
226 | | @brief Remove a single item handle from the sequence |
227 | | */ |
228 | | void SeqSoftRemove(Seq *seq, size_t index); |
229 | | |
230 | | /** |
231 | | @brief Reverses the order of the sequence |
232 | | */ |
233 | | void SeqReverse(Seq *seq); |
234 | | |
235 | | /** |
236 | | @brief Split a sequence in two at a given index. |
237 | | |
238 | | Elements before the split are kept in original sequence, |
239 | | elements after the split are moved to a new sequence, |
240 | | which is returned. The original, the new, and the modified sequence |
241 | | may all be empty. |
242 | | |
243 | | Items in sequence are not reallocated, they are moved and the new |
244 | | sequnce has the same destroy function as the original. |
245 | | |
246 | | @param original [in] The Sequence to split in two (will be modified) |
247 | | @param index [in] Index of split, or how many elements to keep in original |
248 | | @return New sequence containing the elements removed from original |
249 | | */ |
250 | | Seq *SeqSplit(Seq *original, size_t index); |
251 | | |
252 | | /** |
253 | | * @brief Shuffle the sequence by randomly switching positions of the pointers |
254 | | * @param seq |
255 | | * @param seed Seed value for the PRNG |
256 | | */ |
257 | | void SeqShuffle(Seq *seq, unsigned int seed); |
258 | | |
259 | | /** |
260 | | * @brief Remove all elements in sequence |
261 | | * @param seq |
262 | | */ |
263 | | void SeqClear(Seq *seq); |
264 | | |
265 | | /** |
266 | | @brief Get soft copy of sequence according to specified range |
267 | | @param [in] seq Sequence select from |
268 | | @param [in] start Start index of sub sequence. |
269 | | @param [in] end End index which will be included into. |
270 | | @return A pointer to sub sequence, NULL on error. |
271 | | */ |
272 | | Seq *SeqGetRange(const Seq *seq, size_t start, size_t end); |
273 | | |
274 | | /** |
275 | | * @brief Get the data segment of the sequence |
276 | | * @param [in] seq Sequence to get the data segment of |
277 | | * @return An array of pointers to data stored in the sequence |
278 | | * @warning The returned array is not guaranteed to be %NULL-terminated unless %NULL was appended to |
279 | | * the sequence. |
280 | | */ |
281 | | void *const *SeqGetData(const Seq *seq); |
282 | | |
283 | | void SeqRemoveNulls(Seq *seq); |
284 | | |
285 | | Seq *SeqFromArgv(int argc, const char *const *argv); |
286 | | |
287 | | #endif |