WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
zarray.h
Go to the documentation of this file.
1/* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2All rights reserved.
3This software was developed in the APRIL Robotics Lab under the
4direction of Edwin Olson, ebolson@umich.edu. This software may be
5available under alternative licensing terms; contact the address above.
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
81. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
102. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23The views and conclusions contained in the software and documentation are those
24of the authors and should not be interpreted as representing official policies,
25either expressed or implied, of the Regents of The University of Michigan.
26*/
27
28#pragma once
29
30#include <stddef.h>
31#include <assert.h>
32#include <stdlib.h>
33#include <string.h>
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39/**
40 * Defines a structure which acts as a resize-able array ala Java's ArrayList.
41 */
42typedef struct zarray zarray_t;
43struct zarray
44{
45 size_t el_sz; // size of each element
46
47 int size; // how many elements?
48 int alloc; // we've allocated storage for how many elements?
49 char *data;
50};
51
52/**
53 * Creates and returns a variable array structure capable of holding elements of
54 * the specified size. It is the caller's responsibility to call zarray_destroy()
55 * on the returned array when it is no longer needed.
56 */
57static inline zarray_t *zarray_create(size_t el_sz)
58{
59 assert(el_sz > 0);
60
61 zarray_t *za = (zarray_t*) calloc(1, sizeof(zarray_t));
62 za->el_sz = el_sz;
63 return za;
64}
65
66/**
67 * Frees all resources associated with the variable array structure which was
68 * created by zarray_create(). After calling, 'za' will no longer be valid for storage.
69 */
70static inline void zarray_destroy(zarray_t *za)
71{
72 if (za == NULL)
73 return;
74
75 if (za->data != NULL)
76 free(za->data);
77 memset(za, 0, sizeof(zarray_t));
78 free(za);
79}
80
81/** Allocate a new zarray that contains a copy of the data in the argument. **/
82static inline zarray_t *zarray_copy(const zarray_t *za)
83{
84 assert(za != NULL);
85
86 zarray_t *zb = (zarray_t*) calloc(1, sizeof(zarray_t));
87 zb->el_sz = za->el_sz;
88 zb->size = za->size;
89 zb->alloc = za->alloc;
90 zb->data = (char*) malloc(zb->alloc * zb->el_sz);
91 memcpy(zb->data, za->data, za->size * za->el_sz);
92 return zb;
93}
94
95static int iceillog2(int v)
96{
97 v--;
98 v |= v >> 1;
99 v |= v >> 2;
100 v |= v >> 4;
101 v |= v >> 8;
102 v |= v >> 16;
103 v++;
104 return v;
105}
106
107/**
108 * Allocate a new zarray that contains a subset of the original
109 * elements. NOTE: end index is EXCLUSIVE, that is one past the last
110 * element you want.
111 */
112static inline zarray_t *zarray_copy_subset(const zarray_t *za,
113 int start_idx,
114 int end_idx_exclusive)
115{
116 zarray_t *out = (zarray_t*) calloc(1, sizeof(zarray_t));
117 out->el_sz = za->el_sz;
118 out->size = end_idx_exclusive - start_idx;
119 out->alloc = iceillog2(out->size); // round up pow 2
120 out->data = (char*) malloc(out->alloc * out->el_sz);
121 memcpy(out->data, za->data +(start_idx*out->el_sz), out->size*out->el_sz);
122 return out;
123}
124
125/**
126 * Retrieves the number of elements currently being contained by the passed
127 * array, which may be different from its capacity. The index of the last element
128 * in the array will be one less than the returned value.
129 */
130static inline int zarray_size(const zarray_t *za)
131{
132 assert(za != NULL);
133
134 return za->size;
135}
136
137/**
138 * Returns 1 if zarray_size(za) == 0,
139 * returns 0 otherwise.
140 */
141/*
142JUST CALL zarray_size
143int zarray_isempty(const zarray_t *za)
144{
145 assert(za != NULL);
146 if (za->size <= 0)
147 return 1;
148 else
149 return 0;
150}
151*/
152
153
154/**
155 * Allocates enough internal storage in the supplied variable array structure to
156 * guarantee that the supplied number of elements (capacity) can be safely stored.
157 */
158static inline void zarray_ensure_capacity(zarray_t *za, int capacity)
159{
160 assert(za != NULL);
161
162 if (capacity <= za->alloc)
163 return;
164
165 while (za->alloc < capacity) {
166 za->alloc *= 2;
167 if (za->alloc < 8)
168 za->alloc = 8;
169 }
170
171 za->data = (char*) realloc(za->data, za->alloc * za->el_sz);
172}
173
174/**
175 * Adds a new element to the end of the supplied array, and sets its value
176 * (by copying) from the data pointed to by the supplied pointer 'p'.
177 * Automatically ensures that enough storage space is available for the new element.
178 */
179static inline void zarray_add(zarray_t *za, const void *p)
180{
181 assert(za != NULL);
182 assert(p != NULL);
183
184 zarray_ensure_capacity(za, za->size + 1);
185
186 memcpy(&za->data[za->size*za->el_sz], p, za->el_sz);
187 za->size++;
188}
189
190/**
191 * Retrieves the element from the supplied array located at the zero-based
192 * index of 'idx' and copies its value into the variable pointed to by the pointer
193 * 'p'.
194 */
195static inline void zarray_get(const zarray_t *za, int idx, void *p)
196{
197 assert(za != NULL);
198 assert(p != NULL);
199 assert(idx >= 0);
200 assert(idx < za->size);
201
202 memcpy(p, &za->data[idx*za->el_sz], za->el_sz);
203}
204
205/**
206 * Similar to zarray_get(), but returns a "live" pointer to the internal
207 * storage, avoiding a memcpy. This pointer is not valid across
208 * operations which might move memory around (i.e. zarray_remove_value(),
209 * zarray_remove_index(), zarray_insert(), zarray_sort(), zarray_clear()).
210 * 'p' should be a pointer to the pointer which will be set to the internal address.
211 */
212inline static void zarray_get_volatile(const zarray_t *za, int idx, void *p)
213{
214 assert(za != NULL);
215 assert(p != NULL);
216 assert(idx >= 0);
217 assert(idx < za->size);
218
219 *((void**) p) = &za->data[idx*za->el_sz];
220}
221
222inline static void zarray_truncate(zarray_t *za, int sz)
223{
224 assert(za != NULL);
225 assert(sz <= za->size);
226 za->size = sz;
227}
228
229/**
230 * Removes the entry at index 'idx'.
231 * If shuffle is true, the last element in the array will be placed in
232 * the newly-open space; if false, the zarray is compacted.
233 */
234static inline void zarray_remove_index(zarray_t *za, int idx, int shuffle)
235{
236 assert(za != NULL);
237 assert(idx >= 0);
238 assert(idx < za->size);
239
240 if (shuffle) {
241 if (idx < za->size-1)
242 memcpy(&za->data[idx*za->el_sz], &za->data[(za->size-1)*za->el_sz], za->el_sz);
243 za->size--;
244 return;
245 } else {
246 // size = 10, idx = 7. Should copy 2 entries (at idx=8 and idx=9).
247 // size = 10, idx = 9. Should copy 0 entries.
248 int ncopy = za->size - idx - 1;
249 if (ncopy > 0)
250 memmove(&za->data[idx*za->el_sz], &za->data[(idx+1)*za->el_sz], ncopy*za->el_sz);
251 za->size--;
252 return;
253 }
254}
255
256/**
257 * Remove the entry whose value is equal to the value pointed to by 'p'.
258 * If shuffle is true, the last element in the array will be placed in
259 * the newly-open space; if false, the zarray is compacted. At most
260 * one element will be removed.
261 *
262 * Note that objects will be compared using memcmp over the full size
263 * of the value. If the value is a struct that contains padding,
264 * differences in the padding bytes can cause comparisons to
265 * fail. Thus, it remains best practice to bzero all structs so that
266 * the padding is set to zero.
267 *
268 * Returns the number of elements removed (0 or 1).
269 */
270// remove the entry whose value is equal to the value pointed to by p.
271// if shuffle is true, the last element in the array will be placed in
272// the newly-open space; if false, the zarray is compacted.
273static inline int zarray_remove_value(zarray_t *za, const void *p, int shuffle)
274{
275 assert(za != NULL);
276 assert(p != NULL);
277
278 for (int idx = 0; idx < za->size; idx++) {
279 if (!memcmp(p, &za->data[idx*za->el_sz], za->el_sz)) {
280 zarray_remove_index(za, idx, shuffle);
281 return 1;
282 }
283 }
284
285 return 0;
286}
287
288
289/**
290 * Creates a new entry and inserts it into the array so that it will have the
291 * index 'idx' (i.e. before the item which currently has that index). The value
292 * of the new entry is set to (copied from) the data pointed to by 'p'. 'idx'
293 * can be one larger than the current max index to place the new item at the end
294 * of the array, or zero to add it to an empty array.
295 */
296static inline void zarray_insert(zarray_t *za, int idx, const void *p)
297{
298 assert(za != NULL);
299 assert(p != NULL);
300 assert(idx >= 0);
301 assert(idx <= za->size);
302
303 zarray_ensure_capacity(za, za->size + 1);
304 // size = 10, idx = 7. Should copy three entries (idx=7, idx=8, idx=9)
305 int ncopy = za->size - idx;
306
307 memmove(&za->data[(idx+1)*za->el_sz], &za->data[idx*za->el_sz], ncopy*za->el_sz);
308 memcpy(&za->data[idx*za->el_sz], p, za->el_sz);
309
310 za->size++;
311}
312
313
314/**
315 * Sets the value of the current element at index 'idx' by copying its value from
316 * the data pointed to by 'p'. The previous value of the changed element will be
317 * copied into the data pointed to by 'outp' if it is not null.
318 */
319static inline void zarray_set(zarray_t *za, int idx, const void *p, void *outp)
320{
321 assert(za != NULL);
322 assert(p != NULL);
323 assert(idx >= 0);
324 assert(idx < za->size);
325
326 if (outp != NULL)
327 memcpy(outp, &za->data[idx*za->el_sz], za->el_sz);
328
329 memcpy(&za->data[idx*za->el_sz], p, za->el_sz);
330}
331
332/**
333 * Calls the supplied function for every element in the array in index order.
334 * The map function will be passed a pointer to each element in turn and must
335 * have the following format:
336 *
337 * void map_function(element_type *element)
338 */
339static inline void zarray_map(zarray_t *za, void (*f)(void*))
340{
341 assert(za != NULL);
342 assert(f != NULL);
343
344 for (int idx = 0; idx < za->size; idx++)
345 f(&za->data[idx*za->el_sz]);
346}
347
348/**
349 * Calls the supplied function for every element in the array in index order.
350 * HOWEVER values are passed to the function, not pointers to values. In the
351 * case where the zarray stores object pointers, zarray_vmap allows you to
352 * pass in the object's destroy function (or free) directly. Can only be used
353 * with zarray's which contain pointer data. The map function should have the
354 * following format:
355 *
356 * void map_function(element_type *element)
357 */
358 void zarray_vmap(zarray_t *za, void (*f)(void *));
359
360/**
361 * Removes all elements from the array and sets its size to zero. Pointers to
362 * any data elements obtained i.e. by zarray_get_volatile() will no longer be
363 * valid.
364 */
365static inline void zarray_clear(zarray_t *za)
366{
367 assert(za != NULL);
368 za->size = 0;
369}
370
371/**
372 * Determines whether any element in the array has a value which matches the
373 * data pointed to by 'p'.
374 *
375 * Returns 1 if a match was found anywhere in the array, else 0.
376 */
377static inline int zarray_contains(const zarray_t *za, const void *p)
378{
379 assert(za != NULL);
380 assert(p != NULL);
381
382 for (int idx = 0; idx < za->size; idx++) {
383 if (!memcmp(p, &za->data[idx*za->el_sz], za->el_sz)) {
384 return 1;
385 }
386 }
387
388 return 0;
389}
390
391/**
392 * Uses qsort() to sort the elements contained by the array in ascending order.
393 * Uses the supplied comparison function to determine the appropriate order.
394 *
395 * The comparison function will be passed a pointer to two elements to be compared
396 * and should return a measure of the difference between them (see strcmp()).
397 * I.e. it should return a negative number if the first element is 'less than'
398 * the second, zero if they are equivalent, and a positive number if the first
399 * element is 'greater than' the second. The function should have the following format:
400 *
401 * int comparison_function(const element_type *first, const element_type *second)
402 *
403 * zstrcmp() can be used as the comparison function for string elements, which
404 * will call strcmp() internally.
405 */
406static inline void zarray_sort(zarray_t *za, int (*compar)(const void*, const void*))
407{
408 assert(za != NULL);
409 assert(compar != NULL);
410 if (za->size == 0)
411 return;
412
413 qsort(za->data, za->size, za->el_sz, compar);
414}
415
416/**
417 * A comparison function for comparing strings which can be used by zarray_sort()
418 * to sort arrays with char* elements.
419 */
420 int zstrcmp(const void * a_pp, const void * b_pp);
421
422/**
423 * Find the index of an element, or return -1 if not found. Remember that p is
424 * a pointer to the element.
425 **/
426// returns -1 if not in array. Remember p is a pointer to the item.
427static inline int zarray_index_of(const zarray_t *za, const void *p)
428{
429 assert(za != NULL);
430 assert(p != NULL);
431
432 for (int i = 0; i < za->size; i++) {
433 if (!memcmp(p, &za->data[i*za->el_sz], za->el_sz))
434 return i;
435 }
436
437 return -1;
438}
439
440/**
441 * Add elements from start up to and excluding end from 'source' into 'dest'.
442 * el_sz must be the same for both lists
443 **/
444static inline void zarray_add_range(zarray_t *dest, const zarray_t *source, int start, int end)
445{
446 assert(dest->el_sz == source->el_sz);
447 assert(dest != NULL);
448 assert(source != NULL);
449 assert(start >= 0);
450 assert(end <= source->size);
451 if (start == end) {
452 return;
453 }
454 assert(start < end);
455
456 int count = end - start;
457 zarray_ensure_capacity(dest, dest->size + count);
458
459 memcpy(&dest->data[dest->size*dest->el_sz], &source->data[source->el_sz*start], dest->el_sz*count);
460 dest->size += count;
461}
462
463#ifdef __cplusplus
464}
465#endif
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or and nanopb were all modified for use in Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation source
Definition ThirdPartyNotices.txt:124
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or and nanopb were all modified for use in Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable or merely the Work and Derivative Works thereof Contribution shall mean any work of including the original version of the Work and any modifications or additions to that Work or Derivative Works that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner For the purposes of this submitted means any form of or written communication sent to the Licensor or its including but not limited to communication on electronic mailing source code control and issue tracking systems that are managed or on behalf the Licensor for the purpose of discussing and improving the but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as Not a Contribution Contributor shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work Grant of Copyright License Subject to the terms and conditions of this each Contributor hereby grants to You a non no royalty free
Definition ThirdPartyNotices.txt:164
Definition zarray.h:44
int alloc
Definition zarray.h:48
char * data
Definition zarray.h:49
int size
Definition zarray.h:47
size_t el_sz
Definition zarray.h:45
int zstrcmp(const void *a_pp, const void *b_pp)
A comparison function for comparing strings which can be used by zarray_sort() to sort arrays with ch...
static void zarray_remove_index(zarray_t *za, int idx, int shuffle)
Removes the entry at index 'idx'.
Definition zarray.h:234
static int zarray_remove_value(zarray_t *za, const void *p, int shuffle)
Remove the entry whose value is equal to the value pointed to by 'p'.
Definition zarray.h:273
static void zarray_sort(zarray_t *za, int(*compar)(const void *, const void *))
Uses qsort() to sort the elements contained by the array in ascending order.
Definition zarray.h:406
static void zarray_clear(zarray_t *za)
Removes all elements from the array and sets its size to zero.
Definition zarray.h:365
static void zarray_set(zarray_t *za, int idx, const void *p, void *outp)
Sets the value of the current element at index 'idx' by copying its value from the data pointed to by...
Definition zarray.h:319
static void zarray_ensure_capacity(zarray_t *za, int capacity)
Returns 1 if zarray_size(za) == 0, returns 0 otherwise.
Definition zarray.h:158
void zarray_vmap(zarray_t *za, void(*f)(void *))
Calls the supplied function for every element in the array in index order.
static int iceillog2(int v)
Definition zarray.h:95
static void zarray_add_range(zarray_t *dest, const zarray_t *source, int start, int end)
Add elements from start up to and excluding end from 'source' into 'dest'.
Definition zarray.h:444
static void zarray_destroy(zarray_t *za)
Frees all resources associated with the variable array structure which was created by zarray_create()...
Definition zarray.h:70
static void zarray_get(const zarray_t *za, int idx, void *p)
Retrieves the element from the supplied array located at the zero-based index of 'idx' and copies its...
Definition zarray.h:195
static void zarray_map(zarray_t *za, void(*f)(void *))
Calls the supplied function for every element in the array in index order.
Definition zarray.h:339
static int zarray_contains(const zarray_t *za, const void *p)
Determines whether any element in the array has a value which matches the data pointed to by 'p'.
Definition zarray.h:377
static void zarray_insert(zarray_t *za, int idx, const void *p)
Creates a new entry and inserts it into the array so that it will have the index 'idx' (i....
Definition zarray.h:296
static int zarray_size(const zarray_t *za)
Retrieves the number of elements currently being contained by the passed array, which may be differen...
Definition zarray.h:130
static void zarray_truncate(zarray_t *za, int sz)
Definition zarray.h:222
static int zarray_index_of(const zarray_t *za, const void *p)
Find the index of an element, or return -1 if not found.
Definition zarray.h:427
static void zarray_get_volatile(const zarray_t *za, int idx, void *p)
Similar to zarray_get(), but returns a "live" pointer to the internal storage, avoiding a memcpy.
Definition zarray.h:212
static zarray_t * zarray_create(size_t el_sz)
Creates and returns a variable array structure capable of holding elements of the specified size.
Definition zarray.h:57
static void zarray_add(zarray_t *za, const void *p)
Adds a new element to the end of the supplied array, and sets its value (by copying) from the data po...
Definition zarray.h:179
static zarray_t * zarray_copy(const zarray_t *za)
Allocate a new zarray that contains a copy of the data in the argument.
Definition zarray.h:82
static zarray_t * zarray_copy_subset(const zarray_t *za, int start_idx, int end_idx_exclusive)
Allocate a new zarray that contains a subset of the original elements.
Definition zarray.h:112