/** @brief Remove a slice of the dynar, sliding the rest of the values to the left * * This function removes an n-sized slice that starts at element idx. It is equivalent to xbt_dynar_remove_at with a * NULL object argument if n equals to 1. * * Each of the removed elements is freed using the free_f function passed at dynar creation. */ void xbt_dynar_remove_n_at(xbt_dynar_t const dynar, const unsigned int n, const int idx) { unsigned long nb_shift; unsigned long offset; unsigned long cur; if (!n) return; _sanity_check_dynar(dynar); _check_inbound_idx(dynar, idx); _check_inbound_idx(dynar, idx + n - 1); if (dynar->free_f) { for (cur = idx; cur < idx + n; cur++) { dynar->free_f(_xbt_dynar_elm(dynar, cur)); } } nb_shift = dynar->used - n - idx; if (nb_shift) { offset = nb_shift * dynar->elmsize; memmove(_xbt_dynar_elm(dynar, idx), _xbt_dynar_elm(dynar, idx + n), offset); } dynar->used -= n; }
/** @brief Retrieve a copy of the Nth element of a dynar. * * \param dynar information dealer * \param idx index of the slot we want to retrieve * \param[out] dst where to put the result to. */ inline void xbt_dynar_get_cpy(const xbt_dynar_t dynar, const unsigned long idx, void *const dst) { _sanity_check_dynar(dynar); _check_inbound_idx(dynar, idx); _xbt_dynar_get_elm(dst, dynar, idx); }
/** @brief Make room for a new element, and return a pointer to it * * You can then use regular affectation to set its value instead of relying on the slow memcpy. This is what * xbt_dynar_insert_at_as() does. */ void *xbt_dynar_insert_at_ptr(xbt_dynar_t const dynar, const int idx) { void *res; unsigned long old_used; unsigned long new_used; long nb_shift; _sanity_check_dynar(dynar); _sanity_check_idx(idx); old_used = dynar->used; new_used = old_used + 1; _xbt_dynar_expand(dynar, new_used); nb_shift = old_used - idx; if (nb_shift>0) { memmove(_xbt_dynar_elm(dynar, idx + 1), _xbt_dynar_elm(dynar, idx), nb_shift * dynar->elmsize); } dynar->used = new_used; res = _xbt_dynar_elm(dynar, idx); return res; }
/** @brief Remove the Nth dynar's element, sliding the previous values to the left * * 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, const int idx, void *const object) { unsigned long nb_shift; unsigned long offset; _sanity_check_dynar(dynar); _check_inbound_idx(dynar, idx); if (object) { _xbt_dynar_get_elm(object, dynar, idx); } else if (dynar->free_f) { dynar->free_f(_xbt_dynar_elm(dynar, idx)); } nb_shift = dynar->used - 1 - idx; if (nb_shift) { offset = nb_shift * dynar->elmsize; memmove(_xbt_dynar_elm(dynar, idx), _xbt_dynar_elm(dynar, idx + 1), offset); } dynar->used--; }
/** @brief Retrieve a pointer to the Nth element of a dynar. * * \param dynar information dealer * \param idx index of the slot we want to retrieve * \return the \a idx-th element of \a dynar. * * \warning The returned value is the actual content of the dynar. * Make a copy before fooling with it. */ inline void *xbt_dynar_get_ptr(const xbt_dynar_t dynar, const unsigned long idx) { void *res; _sanity_check_dynar(dynar); _check_inbound_idx(dynar, idx); res = _xbt_dynar_elm(dynar, idx); return res; }
/** @brief Frees the content and set the size to 0 * * \param dynar who to squeeze */ inline void xbt_dynar_reset(xbt_dynar_t const dynar) { _sanity_check_dynar(dynar); XBT_CDEBUG(xbt_dyn, "Reset the dynar %p", (void *) dynar); if (dynar->free_f) { xbt_dynar_map(dynar, dynar->free_f); } dynar->used = 0; }
/** @brief Set the Nth element of a dynar (expanded if needed). Previous value is freed * * \param dynar * \param idx * \param object * * Set the Nth element of a dynar, expanding the dynar if needed, AND DO free the previous value at this position. If * you don't want to free the previous content, use xbt_dynar_set(). */ void xbt_dynar_replace(xbt_dynar_t dynar, const unsigned long idx, const void *const object) { _sanity_check_dynar(dynar); if (idx < dynar->used && dynar->free_f) { void *const old_object = _xbt_dynar_elm(dynar, idx); dynar->free_f(old_object); } xbt_dynar_set(dynar, idx, object); }
inline void *xbt_dynar_set_at_ptr(const xbt_dynar_t dynar, const unsigned long idx) { _sanity_check_dynar(dynar); if (idx >= dynar->used) { _xbt_dynar_expand(dynar, idx + 1); if (idx > dynar->used) { memset(_xbt_dynar_elm(dynar, dynar->used), 0, (idx - dynar->used) * dynar->elmsize); } dynar->used = idx + 1; } return _xbt_dynar_elm(dynar, idx); }
/** @brief Apply a function to each member of a dynar * * The mapped function may change the value of the element itself, but should not mess with the structure of the dynar. */ inline void xbt_dynar_map(const xbt_dynar_t dynar, void_f_pvoid_t const op) { char *const data = (char *) dynar->data; const unsigned long elmsize = dynar->elmsize; const unsigned long used = dynar->used; unsigned long i; _sanity_check_dynar(dynar); for (i = 0; i < used; i++) { char* elm = (char*) data + i * elmsize; op(elm); } }