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