Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Another doc improvement
[simgrid.git] / src / xbt / dynar.c
index b964885..4e89515 100644 (file)
 #include "xbt/misc.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
+#include "xbt/ex.h"
 #include "xbt/dynar.h"
 #include <sys/types.h>
 
 #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] */