aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/base/vector.h
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/hicn/base/vector.h')
-rw-r--r--hicn-light/src/hicn/base/vector.h220
1 files changed, 198 insertions, 22 deletions
diff --git a/hicn-light/src/hicn/base/vector.h b/hicn-light/src/hicn/base/vector.h
index 47cfdd11a..06ffa4428 100644
--- a/hicn-light/src/hicn/base/vector.h
+++ b/hicn-light/src/hicn/base/vector.h
@@ -16,55 +16,231 @@
/**
* \file vector.h
* \brief Resizeable static array
+ *
+ * A vector is a resizeable area of contiguous memory that contains elements of
+ * fixed size. It is mostly useful to serve as the basis for more advanced data
+ * structures such as memory pools.
+ *
+ * The internal API manipulates a pointer to the vector so that it can be
+ * seamlessly resized, and a more convenient user interface is provided through
+ * macros.
+ *
+ * A vector starts at index 0, and is typed according to the elements it
+ * contains. For that matter, the data structure header precedes the returned
+ * pointer which corresponds to the storage area.
+ *
+ * A vector is by default used as a stack where an end marker is maintained and
+ * new elements are pushed right after this end marker (an indication of
+ * the size of the vector) after ensuring the vector is sufficiently large.
+ *
+ * A user should not store any pointer to vector elements as this might change
+ * during reallocations, but should use indices instead.
+ *
+ * NOTE: a maximum size is currently not implemented.
+ *
+ * It is freely inspired (and simplified) from the VPP infra infrastructure
+ * library.
*/
#ifndef UTIL_VECTOR_H
#define UTIL_VECTOR_H
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <string.h>
#include <sys/types.h>
#include "common.h"
-/** Local variable naming macro. */
-#define _vector_var(v) _vector_##v
+/******************************************************************************/
+/* Vector header */
typedef struct {
- size_t num_elts;
- size_t max_elts;
+ size_t cur_size; /** Vector current size (corresponding to the highest used element). */
+ size_t max_size; /** The currently allocated size. */
} vector_hdr_t;
-void _vector_init(void ** vector_ptr, size_t elt_size, size_t max_elts);
-void _vector_free(void ** vector_ptr);
-void _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
-
/* Make sure elements following the header are aligned */
#define VECTOR_HDRLEN SIZEOF_ALIGNED(vector_hdr_t)
/* This header actually prepends the actual content of the vector */
#define vector_hdr(vector) ((vector_hdr_t *)((uint8_t*)vector - VECTOR_HDRLEN))
-#define vector_init(vector, max_elts) \
- _vector_init((void**)&vector, sizeof(vector[0]), max_elts)
+/******************************************************************************/
+/* Helpers */
-#define vector_free(vector) \
- _vector_free((void **)&vector)
+/** Local variable naming macro. */
+#define _vector_var(v) _vector_##v
+
+/**
+ * @brief Allocate and initialize a vector data structure (helper function).
+ *
+ * @param[in,out] vector_ptr Vector to allocate and initialize.
+ * @param[in] elt_size Size of a vector element.
+ * @param[in] max_size Maximum vector size (O = unlimited).
+ */
+void _vector_init(void ** vector_ptr, size_t elt_size, size_t max_size);
+
+/**
+ * @brief Free a vector data structure.
+ *
+ * @param vector_ptr[in] Pointer to the vector data structure to free.
+ */
+void _vector_free(void ** vector_ptr);
+
+/**
+ * @brief Resize a vector data structure.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] pos The position at which the vector should be able to hold an
+ * element.
+ *
+ * @return bool Flag indicating whether the vector has been correctly resized.
+ *
+ * NOTE:
+ * - The resize operation does not specify the final size of the vector but
+ * instead ensure that it is large enough to hold an element at the specified
+ * position. This allows the caller not to care about doing successive calls to
+ * this API while the vector is growing in size.
+ */
+bool _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
+
+/**
+ * @brief Ensures a vector is sufficiently large to hold an element at the
+ * given position.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] pos The position to validate.
+ *
+ * @return bool Flag indicating whether the vector is available.
+ *
+ * NOTE:
+ * - This function should always be called before writing to a vector element
+ * to eventually make room for it (the vector will eventually be resized).
+ * - This function can fail if the vector is full and for any reason it cannot
+ * be resized.
+ */
+static inline
+bool
+_vector_ensure_pos(void ** vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t * vh = vector_hdr(*vector_ptr);
+ if (pos >= vh->max_size)
+ return _vector_resize(vector_ptr, elt_size, pos);
+ return true;
+}
-#define vector_len(vector) (vector_hdr(vector)->num_elts)
+/**
+ * @brief Push an element at the end of a vector.
+ *
+ * @param[in] vector_ptr A pointer to the vector data structure to resize.
+ * @param[in] elt_size The size of a vector element.
+ * @param[in] elt The element to insert.
+ *
+ * NOTE:
+ * - This function ensures there is sufficient room for inserting the element,
+ * and evenutually resizes the vector to make room for it (if allowed by
+ * maximum size).
+ */
+static inline
+bool
+_vector_push(void ** vector_ptr, size_t elt_size, void * elt)
+{
+ vector_hdr_t * vh = vector_hdr(*vector_ptr);
+ if (!_vector_ensure_pos(vector_ptr, elt_size, vh->cur_size))
+ return false;
+ /*(*vector_ptr)[vh->cur_size++] = elt; */
+ memcpy((uint8_t*)vector_ptr + vh->cur_size++ * elt_size, elt, elt_size);
+ return true;
+}
+
+/******************************************************************************/
+/* Public API */
+
+/**
+ * @brief Allocate and initialize a vector data structure.
+ *
+ * @param[in,out] vector Vector to allocate and initialize.
+ * @param[in] max_size Maximum vector size (nonzero).
+ */
+#define vector_init(vector, max_size) \
+ _vector_init((void**)&vector, sizeof(vector[0]), max_size)
+/**
+ * @brief Free a vector data structure.
+ *
+ * @param[in] vector The vector data structure to free.
+ */
+#define vector_free(vector) \
+ _vector_free((void**)&vector)
+
+/**
+ * @brief Resize a vector data structure.
+ *
+ * @param[in] vector The vector data structure to resize.
+ * @param[in] pos The position at which the vector should be able to hold an
+ * element.
+ *
+ * @return bool Flag indicating whether the vector has been correctly resized.
+ *
+ * NOTE:
+ * - The resize operation does not specify the final size of the vector but
+ * instead ensure that it is large enough to hold an element at the specified
+ * position. This allows the caller not to care about doing successive calls to
+ * this API while the vector is growing in size.
+ * - If the new size is smaller than the current size, the content of the
+ * vector will be truncated.
+ */
#define vector_resize(vector) _vector_resize((void**)&(vector), sizeof((vector)[0]), 0)
-#define vector_ensure_pos(vector, pos) \
-do { \
- if ((pos) >= vector_hdr(vector)->max_elts) \
- _vector_resize((void**)&(vector), sizeof((vector)[0]), pos); \
-} while(0)
+/**
+ * @brief Ensures a vector is sufficiently large to hold an element at the
+ * given position.
+ *
+ * @param[in] vector The vector for which to validate the position.
+ * @param[in] pos The position to validate.
+ *
+ * NOTE:
+ * - This function should always be called before writing to a vector element
+ * to eventually make room for it (the vector will eventually be resized).
+ */
+#define vector_ensure_pos(vector, pos) \
+ _vector_ensure_pos((void**)&(vector), sizeof((vector)[0]), pos);
-#define vector_push(vector, elt) \
-do { \
- vector_ensure_pos(vector, vector_len(vector)); \
- vector[vector_len(vector)++] = elt; \
+/**
+ * @brief Push an element at the end of a vector.
+ *
+ * @param[in] vector The vector in which to insert the element.
+ * @param[in] elt The element to insert.
+ *
+ * NOTE:
+ * - This function ensures there is sufficient room for inserting the element,
+ * and evenutually resizes the vector to make room for it (if allowed by
+ * maximum size).
+ */
+#define vector_push(vector, elt) \
+do { \
+ typeof(elt) x = elt; \
+ _vector_push((void**)&(vector), sizeof((vector)[0]), (void*)(&x)); \
} while(0)
+/**
+ * @brief Returns the length of a vector.
+ *
+ * @param[in] vector The vector from which to get the size.
+ *
+ * @see vector_ensure_pos
+ *
+ * NOTE:
+ * - The size of the vector corresponds to the highest accessed index (for
+ * example as specified in the resize operation) and not the currently
+ * allocated size which will typically be bigger to amortize allocations.
+ * - A user should always call vector_ensure_pos to ensure the vector is
+ * sufficiently large to hold an element at the specified position.
+ */
+#define vector_len(vector) vector_hdr((vector))->cur_size
+
#endif /* UTIL_VECTOR_H */