GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(dynar,xbt,"Dynamic arrays");
-struct gras_dynar_s {
+typedef struct gras_dynar_s {
unsigned long size;
unsigned long used;
unsigned long elmsize;
void *data;
- void_f_pvoid_t *free;
-};
+ void_f_pvoid_t *free_f;
+} s_gras_dynar_t;
#define __sanity_check_dynar(dynar) \
gras_assert0(dynar, \
static _GRAS_INLINE
gras_error_t
-_gras_dynar_expand(gras_dynar_t * const dynar,
- const int nb) {
+_gras_dynar_expand(gras_dynar_t const dynar,
+ const int nb) {
gras_error_t errcode = no_error;
const unsigned long old_size = dynar->size;
static _GRAS_INLINE
void *
-_gras_dynar_elm(const gras_dynar_t * const dynar,
- const unsigned long idx) {
+_gras_dynar_elm(const gras_dynar_t dynar,
+ const unsigned long idx) {
char * const data = dynar->data;
const unsigned long elmsize = dynar->elmsize;
static _GRAS_INLINE
void
-_gras_dynar_get_elm(void * const dst,
- const gras_dynar_t * const dynar,
- const unsigned long idx) {
+_gras_dynar_get_elm(void * const dst,
+ const gras_dynar_t dynar,
+ const unsigned long idx) {
void * const elm = _gras_dynar_elm(dynar, idx);
const unsigned long elmsize = dynar->elmsize;
static _GRAS_INLINE
void
-_gras_dynar_put_elm(const gras_dynar_t * const dynar,
- const unsigned long idx,
- const void * const src) {
+_gras_dynar_put_elm(const gras_dynar_t dynar,
+ const unsigned long idx,
+ const void * const src) {
void * const elm = _gras_dynar_elm(dynar, idx);
const unsigned long elmsize = dynar->elmsize;
* pointer of pointer. That is to say that dynars can contain either base
* types (int, char, double, etc) or pointer of pointers (struct **).
*/
-gras_dynar_t *
+gras_dynar_t
gras_dynar_new(const unsigned long elmsize,
- void_f_pvoid_t * const free_func) {
+ void_f_pvoid_t * const free_f) {
- gras_dynar_t *dynar = gras_new0(gras_dynar_t,1);
+ gras_dynar_t dynar = gras_new0(s_gras_dynar_t,1);
dynar->size = 0;
dynar->used = 0;
dynar->elmsize = elmsize;
dynar->data = NULL;
- dynar->free = free_func;
+ dynar->free_f = free_f;
return dynar;
}
* its contain points to.
*/
void
-gras_dynar_free_container(gras_dynar_t * const dynar) {
- if (dynar) {
+gras_dynar_free_container(gras_dynar_t *dynar) {
+ if (dynar && *dynar) {
- if (dynar->data) {
- _gras_clear_mem(dynar->data, dynar->size);
- gras_free(dynar->data);
+ if ((*dynar)->data) {
+ _gras_clear_mem((*dynar)->data, (*dynar)->size);
+ gras_free((*dynar)->data);
}
- _gras_clear_mem(dynar, sizeof(gras_dynar_t));
+ _gras_clear_mem(*dynar, sizeof(s_gras_dynar_t));
- gras_free(dynar);
+ gras_free(*dynar);
+ *dynar=NULL;
}
}
* Frees the content and set the size to 0
*/
void
-gras_dynar_reset(gras_dynar_t * const dynar) {
+gras_dynar_reset(gras_dynar_t const dynar) {
__sanity_check_dynar(dynar);
DEBUG1("Reset the dynar %p",(void*)dynar);
- if (dynar->free) {
- gras_dynar_map(dynar, dynar->free);
+ if (dynar->free_f) {
+ gras_dynar_map(dynar, dynar->free_f);
}
- if (dynar->data) {
- _gras_clear_mem(dynar->data, dynar->size);
+ if (dynar->data)
gras_free(dynar->data);
- }
dynar->size = 0;
dynar->used = 0;
*/
void
-gras_dynar_free(gras_dynar_t * const dynar) {
- if (dynar) {
- gras_dynar_reset(dynar);
+gras_dynar_free(gras_dynar_t * dynar) {
+ if (dynar && *dynar) {
+ gras_dynar_reset(*dynar);
gras_dynar_free_container(dynar);
}
}
* Returns the count of elements in a dynar
*/
unsigned long
-gras_dynar_length(const gras_dynar_t * const dynar) {
+gras_dynar_length(const gras_dynar_t dynar) {
return (dynar ? (unsigned long) dynar->used : (unsigned long)0);
}
* Retrieve a copy of the Nth element of a dynar.
*/
void
-gras_dynar_get_cpy(const gras_dynar_t * const dynar,
- const int idx,
- void * const dst) {
+gras_dynar_get_cpy(const gras_dynar_t dynar,
+ const int idx,
+ void * const dst) {
__sanity_check_dynar(dynar);
__sanity_check_idx(idx);
* the dynar. Make a copy before fooling with it.
*/
void*
-gras_dynar_get_ptr(const gras_dynar_t * const dynar,
- const int idx) {
+gras_dynar_get_ptr(const gras_dynar_t dynar,
+ const int idx) {
__sanity_check_dynar(dynar);
__sanity_check_idx(idx);
*
* Set the Nth element of a dynar, expanding the dynar if needed, BUT NOT freeing
* the previous value at this position. If you want to free the previous content,
- * use gras_dynar_remplace().
+ * use gras_dynar_replace().
*/
void
-gras_dynar_set(gras_dynar_t * const dynar,
+gras_dynar_set(gras_dynar_t dynar,
const int idx,
const void * const src) {
}
/**
- * gras_dynar_remplace:
+ * gras_dynar_replace:
* @dynar:
* @idx:
* @object:
* previous content, use gras_dynar_set().
*/
void
-gras_dynar_remplace(gras_dynar_t * const dynar,
- const int idx,
- const void * const object) {
+gras_dynar_replace(gras_dynar_t dynar,
+ const int idx,
+ const void * const object) {
__sanity_check_dynar(dynar);
__sanity_check_idx(idx);
- if (idx < dynar->used && dynar->free) {
+ if (idx < dynar->used && dynar->free_f) {
void * const old_object = _gras_dynar_elm(dynar, idx);
- dynar->free(old_object);
+ dynar->free_f(old_object);
}
gras_dynar_set(dynar, idx, object);
}
/**
- * gras_dynar_insert_at:
- * @dynar:
- * @idx:
- * @src: What will be feeded to the dynar
- *
- * Set the Nth element of a dynar, expanding the dynar if needed, and
- * moving the previously existing value and all subsequent ones to one
- * position right in the dynar.
+ * gras_dynar_insert_at_ptr:
+ *
+ * Make room for a new element in the dynar, and return a pointer to
+ * its position. You can then use regular affectation to set its value
+ * instead of relying on the slow memcpy
*/
-void
-gras_dynar_insert_at(gras_dynar_t * const dynar,
- const int idx,
- const void * const src) {
-
+void *
+gras_dynar_insert_at_ptr(gras_dynar_t const dynar,
+ const int idx) {
+
__sanity_check_dynar(dynar);
__sanity_check_idx(idx);
__check_sloppy_inbound_idx(dynar, idx);
{
const unsigned long nb_shift = old_used - idx;
- const unsigned long elmsize = dynar->elmsize;
- const unsigned long offset = nb_shift*elmsize;
-
- void * const elm_src = _gras_dynar_elm(dynar, idx);
- void * const elm_dst = _gras_dynar_elm(dynar, idx+1);
-
- memmove(elm_dst, elm_src, offset);
+ if (nb_shift)
+ memmove(_gras_dynar_elm(dynar, idx+1),
+ _gras_dynar_elm(dynar, idx),
+ nb_shift * dynar->elmsize);
}
- _gras_dynar_put_elm(dynar, idx, src);
dynar->used = new_used;
+ return _gras_dynar_elm(dynar,idx);
}
}
+/**
+ * gras_dynar_insert_at:
+ * @dynar:
+ * @idx:
+ * @src: What will be feeded to the dynar
+ *
+ * Set the Nth element of a dynar, expanding the dynar if needed, and
+ * moving the previously existing value and all subsequent ones to one
+ * position right in the dynar.
+ */
+void
+gras_dynar_insert_at(gras_dynar_t const dynar,
+ const int idx,
+ const void * const src) {
+
+ /* checks done in gras_dynar_insert_at_ptr */
+ memcpy(gras_dynar_insert_at_ptr(dynar,idx),
+ src,
+ dynar->elmsize);
+}
+
/**
* gras_dynar_remove_at:
* @dynar:
* all subsequent values to one position left in the dynar.
*/
void
-gras_dynar_remove_at(gras_dynar_t * const dynar,
+gras_dynar_remove_at(gras_dynar_t const dynar,
const int idx,
void * const object) {
}
}
+/**
+ * gras_dynar_push_ptr:
+ *
+ * Make room at the end of the dynar for a new element, and return a pointer to it
+ */
+void *
+gras_dynar_push_ptr(gras_dynar_t const dynar) {
+ return gras_dynar_insert_at_ptr(dynar, dynar->used);
+}
+
/**
* gras_dynar_push:
* @dynar:
* Add an element at the end of the dynar
*/
void
-gras_dynar_push(gras_dynar_t * const dynar,
+gras_dynar_push(gras_dynar_t const dynar,
const void * const src) {
- __sanity_check_dynar(dynar);
- gras_dynar_insert_at(dynar, dynar->used, src);
+ /* sanity checks done by insert_at */
+ gras_dynar_insert_at(dynar, dynar->used, src);
+}
+
+/**
+ * gras_dynar_pop_ptr:
+ * @dynar:
+ * @dst:
+ *
+ * Make the last element of the dynar as unused and return a pointer to it.
+ */
+void *
+gras_dynar_pop_ptr(gras_dynar_t const dynar) {
+
+ __check_populated_dynar(dynar);
+ DEBUG1("Pop %p",(void*)dynar);
+ dynar->used--;
+ return _gras_dynar_elm(dynar,dynar->used);
}
/**
* Get and remove the last element of the dynar
*/
void
-gras_dynar_pop(gras_dynar_t * const dynar,
+gras_dynar_pop(gras_dynar_t const dynar,
void * const dst) {
- __sanity_check_dynar(dynar);
- __check_populated_dynar(dynar);
+
+ /* sanity checks done by remove_at */
DEBUG1("Pop %p",(void*)dynar);
gras_dynar_remove_at(dynar, dynar->used-1, dst);
}
* gras_dynar_push() when possible)
*/
void
-gras_dynar_unshift(gras_dynar_t * const dynar,
+gras_dynar_unshift(gras_dynar_t const dynar,
const void * const src) {
- __sanity_check_dynar(dynar);
+
+ /* sanity checks done by insert_at */
gras_dynar_insert_at(dynar, 0, src);
}
* gras_dynar_pop() when possible)
*/
void
-gras_dynar_shift(gras_dynar_t * const dynar,
+gras_dynar_shift(gras_dynar_t const dynar,
void * const dst) {
- __sanity_check_dynar(dynar);
- __check_populated_dynar(dynar);
+ /* sanity checks done by remove_at */
gras_dynar_remove_at(dynar, 0, dst);
}
* value of the element itself, but should not mess with the dynar).
*/
void
-gras_dynar_map(const gras_dynar_t * const dynar,
+gras_dynar_map(const gras_dynar_t dynar,
void_f_pvoid_t * const operator) {
__sanity_check_dynar(dynar);
*
*/
void
-gras_dynar_cursor_first(const gras_dynar_t * const dynar,
- int * const cursor) {
+gras_dynar_cursor_first(const gras_dynar_t dynar,
+ int * const cursor) {
- __sanity_check_dynar(dynar);
DEBUG1("Set cursor on %p to the first position",(void*)dynar);
*cursor = 0;
}
* Move the cursor to the next value (and return true), or return false.
*/
void
-gras_dynar_cursor_step(const gras_dynar_t * const dynar,
- int * const cursor) {
+gras_dynar_cursor_step(const gras_dynar_t dynar,
+ int * const cursor) {
- __sanity_check_dynar(dynar);
(*cursor)++;
}
* Get the current value of the cursor
*/
int
-gras_dynar_cursor_get(const gras_dynar_t * const dynar,
+gras_dynar_cursor_get(const gras_dynar_t dynar,
int * const cursor,
void * const dst) {
*
* Remove (free) the entry pointed by the cursor, for use in the middle of a foreach
*/
-void gras_dynar_cursor_rm(gras_dynar_t * dynar,
+void gras_dynar_cursor_rm(gras_dynar_t dynar,
int * const cursor) {
void *dst;
if (dynar->elmsize > sizeof(void*)) {
DEBUG0("Elements too big to fit into a pointer");
- if (dynar->free) {
+ if (dynar->free_f) {
dst=gras_malloc(dynar->elmsize);
gras_dynar_remove_at(dynar,(*cursor)--,dst);
- (dynar->free)(dst);
+ (dynar->free_f)(dst);
gras_free(dst);
} else {
- DEBUG0("Ok, we dont care about the element when no free function");
+ DEBUG0("Ok, we dont care about the element without free function");
gras_dynar_remove_at(dynar,(*cursor)--,NULL);
}
} else {
gras_dynar_remove_at(dynar,(*cursor)--,&dst);
- if (dynar->free)
- (dynar->free)(dst);
+ if (dynar->free_f)
+ (dynar->free_f)(dst);
}
}