1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/* dynar - a generic dynamic array */
/* Copyright (c) 2004-2025. The SimGrid Team. All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
#ifndef XBT_DYNAR_H
#define XBT_DYNAR_H
#include <string.h> /* memcpy */
#include <xbt/base.h> /* SG_BEGIN_DECL */
#include <xbt/function_types.h>
SG_BEGIN_DECL
/** @brief Dynar data type (opaque type)
*
* These are the SimGrid version of the DYNamically sized ARays, which all C programmer recode one day or another.
* For performance concerns, the content of dynars must be homogeneous (in contrary to
* @verbatim embed:rst:inline :cpp:type:`xbt_dict_t` @endverbatim ).
* You thus have to provide the function which will be used to free the content at
* structure creation (of type void_f_pvoid_t).
*/
typedef struct xbt_dynar_s *xbt_dynar_t;
/** constant dynar */
typedef const struct xbt_dynar_s* const_xbt_dynar_t;
/* @warning DO NOT USE THIS STRUCTURE DIRECTLY! Use the public interface, even if it's public for sake of inlining */
typedef struct xbt_dynar_s {
unsigned long size;
unsigned long used;
unsigned long elmsize;
void* data;
void_f_pvoid_t free_f;
} s_xbt_dynar_t;
XBT_PUBLIC xbt_dynar_t xbt_dynar_new(const unsigned long elm_size, void_f_pvoid_t free_f);
XBT_PUBLIC void xbt_dynar_free(xbt_dynar_t* dynar);
XBT_PUBLIC void xbt_dynar_free_container(xbt_dynar_t* dynar);
/* Dynar as a regular array */
XBT_PUBLIC void xbt_dynar_get_cpy(const_xbt_dynar_t dynar, unsigned long idx, void* dst);
XBT_PUBLIC void xbt_dynar_insert_at(xbt_dynar_t dynar, int idx, const void* src);
XBT_PUBLIC void xbt_dynar_remove_at(xbt_dynar_t dynar, int idx, void* dst);
XBT_PUBLIC int xbt_dynar_member(const_xbt_dynar_t dynar, const void* elem);
XBT_PUBLIC void xbt_dynar_sort(const_xbt_dynar_t dynar, int_f_cpvoid_cpvoid_t compar_fn);
/* Dynar size */
XBT_PUBLIC void xbt_dynar_reset(xbt_dynar_t dynar);
XBT_PUBLIC unsigned long xbt_dynar_length(const_xbt_dynar_t dynar);
XBT_PUBLIC int xbt_dynar_is_empty(const_xbt_dynar_t dynar);
/* Perl-like interface */
XBT_PUBLIC void xbt_dynar_push(xbt_dynar_t dynar, const void* src);
XBT_PUBLIC void xbt_dynar_pop(xbt_dynar_t dynar, void* dst);
XBT_PUBLIC void xbt_dynar_unshift(xbt_dynar_t dynar, const void* src);
XBT_PUBLIC void xbt_dynar_shift(xbt_dynar_t dynar, void* dst);
XBT_PUBLIC void xbt_dynar_map(const_xbt_dynar_t dynar, void_f_pvoid_t op);
/* Direct content manipulation*/
XBT_PUBLIC void* xbt_dynar_set_at_ptr(const xbt_dynar_t dynar, unsigned long idx);
XBT_PUBLIC void* xbt_dynar_get_ptr(const_xbt_dynar_t dynar, unsigned long idx);
XBT_PUBLIC void* xbt_dynar_insert_at_ptr(xbt_dynar_t dynar, int idx);
XBT_PUBLIC void* xbt_dynar_push_ptr(xbt_dynar_t dynar);
XBT_PUBLIC void* xbt_dynar_pop_ptr(xbt_dynar_t dynar);
/* Dynars of scalar */
/** @brief Quick retrieval of scalar content
* @hideinitializer */
# define xbt_dynar_get_as(dynar,idx,type) \
(*(type*)xbt_dynar_get_ptr((dynar),(idx)))
/** @brief Quick setting of scalar content
* @hideinitializer */
#define xbt_dynar_set_as(dynar, idx, type, val) (*(type*)xbt_dynar_set_at_ptr((dynar), (idx))) = (val)
/** @brief Quick retrieval of scalar content
* @hideinitializer */
# define xbt_dynar_getlast_as(dynar,type) \
(*(type*)xbt_dynar_get_ptr((dynar),xbt_dynar_length(dynar)-1))
/** @brief Quick retrieval of scalar content
* @hideinitializer */
# define xbt_dynar_getfirst_as(dynar,type) \
(*(type*)xbt_dynar_get_ptr((dynar),0))
/** @brief Quick insertion of scalar content
* @hideinitializer */
#define xbt_dynar_push_as(dynar, type, value) *(type*)xbt_dynar_push_ptr(dynar) = (value)
/** @brief Quick removal of scalar content
* @hideinitializer */
# define xbt_dynar_pop_as(dynar,type) \
(*(type*)xbt_dynar_pop_ptr(dynar))
/* Iterating over dynars */
static inline int _xbt_dynar_cursor_get(const_xbt_dynar_t dynar, unsigned int idx, void* dst)
{
if (!dynar) /* iterating over a NULL dynar is a no-op */
return 0;
if (idx >= dynar->used)
return 0;
memcpy(dst, ((char *) dynar->data) + idx * dynar->elmsize, dynar->elmsize);
return 1;
}
/** @brief Iterates over the whole dynar.
*
* @param _dynar what to iterate over
* @param _cursor an unsigned integer used as cursor
* @hideinitializer
*
* Here is an example of usage:
* @code
xbt_dynar_t dyn;
unsigned int cpt;
char* str;
xbt_dynar_foreach (dyn,cpt,str) {
printf("Seen %s\n",str);
}
@endcode
*
* Note that underneath, that's a simple for loop with no real black magic involved. It's perfectly safe to interrupt
* a foreach with a break or a return statement, but inserting or removing elements during the traversal is probably a
* bad idea (even if you can fix side effects by manually changing the counter).
*/
#define xbt_dynar_foreach(_dynar, _cursor, _data) \
for ((_cursor) = 0; _xbt_dynar_cursor_get((_dynar), (_cursor), &(_data)); (_cursor)++)
SG_END_DECL
#endif /* XBT_DYNAR_H */
|