X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/a3427ca7c9f8f2563bb982044e1082cc8f3cdd1e..3d76f7a607a4a2276129981a632e3a9cd911be84:/src/xbt/dynar.c diff --git a/src/xbt/dynar.c b/src/xbt/dynar.c index b964885adb..4e895153bf 100644 --- a/src/xbt/dynar.c +++ b/src/xbt/dynar.c @@ -11,13 +11,14 @@ #include "xbt/misc.h" #include "xbt/sysdep.h" #include "xbt/log.h" +#include "xbt/ex.h" #include "xbt/dynar.h" #include #include "xbt/dynar_private.h" /* type definition, which we share with the code in charge of sending this across the net */ -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(dynar,xbt,"Dynamic arrays"); +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_dyn,xbt,"Dynamic arrays"); #define __sanity_check_dynar(dynar) \ @@ -33,19 +34,19 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(dynar,xbt,"Dynamic arrays"); (int) (idx), (unsigned long) dynar->used) #define __check_sloppy_inbound_idx(dynar, idx) \ xbt_assert2(idx <= dynar->used, \ - "dynar is not that long. You asked %d, but it's only %lu long", \ + "dynar is not that long. You asked %d, but it's only %lu long (could have been equal to it)", \ (int) (idx), (unsigned long) dynar->used) #define __check_populated_dynar(dynar) \ xbt_assert1(dynar->used, \ "dynar %p contains nothing",(void*)dynar) -static _XBT_INLINE +static XBT_INLINE void _xbt_clear_mem(void * const ptr, const unsigned long length) { memset(ptr, 0, length); } -static _XBT_INLINE +static XBT_INLINE void _xbt_dynar_expand(xbt_dynar_t const dynar, const int nb) { @@ -79,7 +80,7 @@ _xbt_dynar_expand(xbt_dynar_t const dynar, } } -static _XBT_INLINE +static XBT_INLINE void * _xbt_dynar_elm(const xbt_dynar_t dynar, const unsigned long idx) { @@ -89,18 +90,17 @@ _xbt_dynar_elm(const xbt_dynar_t dynar, return data + idx*elmsize; } -static _XBT_INLINE +static XBT_INLINE void _xbt_dynar_get_elm(void * const dst, const xbt_dynar_t dynar, const unsigned long idx) { void * const elm = _xbt_dynar_elm(dynar, idx); - const unsigned long elmsize = dynar->elmsize; - memcpy(dst, elm, elmsize); + memcpy(dst, elm, dynar->elmsize); } -static _XBT_INLINE +static XBT_INLINE void _xbt_dynar_put_elm(const xbt_dynar_t dynar, const unsigned long idx, @@ -127,7 +127,7 @@ xbt_dynar_dump(xbt_dynar_t dynar) { * types (int, char, double, etc) or pointer of pointers (struct **). */ xbt_dynar_t -xbt_dynar_new(const unsigned long elmsize, +xbt_dynar_new(const unsigned long elmsize, void_f_pvoid_t * const free_f) { xbt_dynar_t dynar = xbt_new0(s_xbt_dynar_t,1); @@ -187,6 +187,29 @@ xbt_dynar_reset(xbt_dynar_t const dynar) { /* dynar->data = NULL;*/ } +/** + * \brief Shrink the dynar by removing empty slots at the end of the internal array + * \param dynar a dynar + * \param empty_slots_wanted number of empty slots you want to keep at the end of the + * internal array for further insertions + * + * Reduces the internal array size of the dynar to the number of elements plus + * \a empty_slots_wanted. + * After removing elements from the dynar, you can call this function to make + * the dynar use less memory. + * Set \a empty_slots_wanted to zero to reduce the dynar internal array as much + * as possible. + * Note that if \a empty_slots_wanted is greater than the array size, the internal + * array is not expanded and nothing is done. + */ +void xbt_dynar_shrink(xbt_dynar_t dynar, int empty_slots_wanted) { + int size_wanted = dynar->used + empty_slots_wanted; + if (size_wanted < dynar->size) { + dynar->size = size_wanted; + dynar->data = xbt_realloc(dynar->data, sizeof(void*) * dynar->size); + } +} + /** @brief Destructor * * \param dynar poor victim @@ -243,8 +266,7 @@ xbt_dynar_get_cpy(const xbt_dynar_t dynar, * Make a copy before fooling with it. */ void* -xbt_dynar_get_ptr(const xbt_dynar_t dynar, - const int idx) { +xbt_dynar_get_ptr(const xbt_dynar_t dynar, const int idx) { __sanity_check_dynar(dynar); __sanity_check_idx(idx); @@ -359,6 +381,10 @@ xbt_dynar_insert_at(xbt_dynar_t const dynar, * * Get the Nth element of a dynar, removing it from the dynar and moving * all subsequent values to one position left in the dynar. + * + * If the object argument of this function is a non-null pointer, the removed + * element is copied to this address. If not, the element is freed using the + * free_f function passed at dynar creation. */ void xbt_dynar_remove_at(xbt_dynar_t const dynar, @@ -375,9 +401,16 @@ xbt_dynar_remove_at(xbt_dynar_t const dynar, if (object) { _xbt_dynar_get_elm(object, dynar, idx); } else if (dynar->free_f) { - char elm[SIZEOF_MAX]; - _xbt_dynar_get_elm(elm, dynar, idx); - (*dynar->free_f)(elm); + if (dynar->elmsize <= SIZEOF_MAX) { + char elm[SIZEOF_MAX]; + _xbt_dynar_get_elm(elm, dynar, idx); + (*dynar->free_f)(elm); + } else { + char *elm=malloc(dynar->elmsize); + _xbt_dynar_get_elm(elm, dynar, idx); + (*dynar->free_f)(elm); + free(elm); + } } nb_shift = dynar->used-1 - idx; @@ -390,6 +423,41 @@ xbt_dynar_remove_at(xbt_dynar_t const dynar, dynar->used--; } +/** @brief Returns the position of the element in the dynar + * + * Raises not_found_error if not found. + */ +int +xbt_dynar_search(xbt_dynar_t const dynar, + void *const elem) { + int it; + + for (it=0; it< dynar->size; it++) + if (!memcmp(_xbt_dynar_elm(dynar, it),elem,dynar->elmsize)) + return it; + + THROW2(not_found_error,0,"Element %p not part of dynar %p",elem,dynar); +} + +/** @brief Returns a boolean indicating whether the element is part of the dynar */ +int +xbt_dynar_member(xbt_dynar_t const dynar, + void *const elem) { + + xbt_ex_t e; + + TRY { + xbt_dynar_search(dynar,elem); + } CATCH(e) { + if (e.category == not_found_error) { + xbt_ex_free(e); + return 0; + } + RETHROW; + } + return 1; +} + /** @brief Make room at the end of the dynar for a new element, and return a pointer to it. * * You can then use regular affectation to set its value instead of relying @@ -555,8 +623,8 @@ void xbt_dynar_cursor_rm(xbt_dynar_t dynar, #define NB_ELEM 5000 XBT_TEST_SUITE("dynar","Dynar data container"); -XBT_LOG_EXTERNAL_CATEGORY(dynar); -XBT_LOG_DEFAULT_CATEGORY(dynar); +XBT_LOG_EXTERNAL_CATEGORY(xbt_dyn); +XBT_LOG_DEFAULT_CATEGORY(xbt_dyn); XBT_TEST_UNIT("int",test_dynar_int,"Dyars of integers") { /* Vars_decl [doxygen cruft] */