From cf3429b93444293d131cd0c90df285e7644907d9 Mon Sep 17 00:00:00 2001 From: Kevin Harwell Date: Tue, 25 Apr 2017 11:43:26 -0500 Subject: vector: defaults and indexes Added an pre-defined integer vector declaration. This makes integer vectors easier to declare and pass around. Also, added the ability to default a vector up to a given size with a default value. Lastly, added functionality that returns the "nth" index of a matching value. Also, updated a unit test to test these changes. Change-Id: Iaf4b51b2540eda57cb43f67aa59cf1d96cdbcaa5 --- include/asterisk/vector.h | 62 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test_vector.c | 19 +++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/include/asterisk/vector.h b/include/asterisk/vector.h index 83732e7c8..2de84d295 100644 --- a/include/asterisk/vector.h +++ b/include/asterisk/vector.h @@ -48,6 +48,9 @@ size_t current; \ } +/*! \brief Integer vector definition */ +AST_VECTOR(ast_vector_int, int); + /*! * \brief Define a vector structure with a read/write lock * @@ -240,6 +243,29 @@ res; \ }) +/*! + * \brief Default a vector up to size with the given value. + * + * \note If a size of 0 is given then all elements in the given vector are set. + * \note The vector will grow to the given size if needed. + * + * \param vec Vector to default. + * \param size The number of elements to default + * \param value The default value to set each element to + */ +#define AST_VECTOR_DEFAULT(vec, size, value) ({ \ + int res = 0; \ + typeof((size)) __size = (size) ? (size) : AST_VECTOR_SIZE(vec); \ + size_t idx; \ + for (idx = 0; idx < __size; ++idx) { \ + res = AST_VECTOR_REPLACE(vec, idx, value); \ + if (res == -1) { \ + break; \ + } \ + } \ + res; \ +}) + /*! * \brief Insert an element at a specific position in a vector, growing the vector if needed. * @@ -552,6 +578,42 @@ (vec)->elems[__idx]; \ }) +/*! + * \brief Get the nth index from a vector that matches the given comparison + * + * \param vec Vector to get from. + * \param nth The nth index to find + * \param value Value to pass into comparator. + * \param cmp Comparator function/macros (called as \c cmp(elem, value)) + * + * \return a pointer to the element that was found or NULL + */ +#define AST_VECTOR_GET_INDEX_NTH(vec, nth, value, cmp) ({ \ + int res = -1; \ + size_t idx; \ + typeof(nth) __nth = (nth); \ + typeof(value) __value = (value); \ + for (idx = 0; idx < (vec)->current; ++idx) { \ + if (cmp((vec)->elems[idx], __value) && !(--__nth)) { \ + res = (int)idx; \ + break; \ + } \ + } \ + res; \ +}) + +/*! + * \brief Get the 1st index from a vector that matches the given comparison + * + * \param vec Vector to get from. + * \param value Value to pass into comparator. + * \param cmp Comparator function/macros (called as \c cmp(elem, value)) + * + * \return a pointer to the element that was found or NULL + */ +#define AST_VECTOR_GET_INDEX(vec, value, cmp) \ + AST_VECTOR_GET_INDEX_NTH(vec, 1, value, cmp) + /*! * \brief Get an element from a vector that matches the given comparison * diff --git a/tests/test_vector.c b/tests/test_vector.c index 8ca4efa1a..8e0d121dd 100644 --- a/tests/test_vector.c +++ b/tests/test_vector.c @@ -282,6 +282,25 @@ AST_TEST_DEFINE(basic_ops_integer) ast_test_validate_cleanup(test, *(int *)AST_VECTOR_GET_CMP(&sv1, AAA, AST_VECTOR_ELEM_DEFAULT_CMP) == AAA, rc, cleanup); ast_test_validate_cleanup(test, *(int *)AST_VECTOR_GET_CMP(&sv1, ZZZ, AST_VECTOR_ELEM_DEFAULT_CMP) == ZZZ, rc, cleanup); + /* Default first value */ + ast_test_validate_cleanup(test, AST_VECTOR_DEFAULT(&sv1, 1, CCC) == 0, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == CCC, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == ZZZ, rc, cleanup); + /* Default all values */ + ast_test_validate_cleanup(test, AST_VECTOR_DEFAULT(&sv1, 0, AAA) == 0, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 0) == AAA, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 1) == AAA, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 2) == AAA, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 3) == AAA, rc, cleanup); + /* Default more values than are currently in the vector */ + ast_test_validate_cleanup(test, AST_VECTOR_DEFAULT(&sv1, 5, BBB) == 0, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET(&sv1, 4) == BBB, rc, cleanup); + + /* Check getting index(es) */ + ast_test_validate_cleanup(test, AST_VECTOR_GET_INDEX(&sv1, BBB, AST_VECTOR_ELEM_DEFAULT_CMP) == 0, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET_INDEX_NTH(&sv1, 2, BBB, AST_VECTOR_ELEM_DEFAULT_CMP) == 1, rc, cleanup); + ast_test_validate_cleanup(test, AST_VECTOR_GET_INDEX_NTH(&sv1, 4, BBB, AST_VECTOR_ELEM_DEFAULT_CMP) == 3, rc, cleanup); + AST_VECTOR_FREE(&sv1); ast_test_validate(test, sv1.elems == NULL); ast_test_validate(test, sv1.current == 0); -- cgit v1.2.3