Skip to content

Commit

Permalink
Merge branch 'master' into cvector-macro
Browse files Browse the repository at this point in the history
  • Loading branch information
eteran authored Oct 31, 2023
2 parents 03281a5 + d6cb7c2 commit 576e5ec
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 13 deletions.
64 changes: 55 additions & 9 deletions cvector.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,39 @@
#ifndef CVECTOR_H_
#define CVECTOR_H_

#include <assert.h> /* for assert */
#include <stdlib.h> /* for malloc/realloc/free */
#include <string.h> /* for memcpy/memmove */

/* cvector heap implemented using C library malloc() */

/* in case C library malloc() needs extra protection,
* allow these defines to be overridden.
*/
#ifndef cvector_clib_free
#include <stdlib.h> /* for free */
#define cvector_clib_free free
#endif
#ifndef cvector_clib_malloc
#include <stdlib.h> /* for malloc */
#define cvector_clib_malloc malloc
#endif
#ifndef cvector_clib_calloc
#include <stdlib.h> /* for calloc */
#define cvector_clib_calloc calloc
#endif
#ifndef cvector_clib_realloc
#include <stdlib.h> /* for realloc */
#define cvector_clib_realloc realloc
#endif
#ifndef cvector_clib_assert
#include <assert.h> /* for assert */
#define cvector_clib_assert assert
#endif
#ifndef cvector_clib_memcpy
#include <string.h> /* for memcpy */
#define cvector_clib_memcpy memcpy
#endif
#ifndef cvector_clib_memmove
#include <string.h> /* for memmove */
#define cvector_clib_memmove memmove
#endif

typedef void (*cvector_elem_destructor_t)(void *elem);

Expand All @@ -49,6 +61,11 @@ typedef struct cvector_metadata_t {
*/
#define cvector(type) cvector_vector_type(type)

/*
* @brief cvector_iterator - The iterator type used for cvector
*/
#define cvector_iterator(type) cvector_vector_type(type)

/**
* @brief cvector_vec_to_base - For internal use, converts a vector pointer to a metadata pointer
* @param vec - the vector
Expand Down Expand Up @@ -146,7 +163,7 @@ typedef struct cvector_metadata_t {
elem_destructor__(&(vec)[i]); \
} \
cvector_set_size((vec), cv_sz__ - 1); \
memmove( \
cvector_clib_memmove( \
(vec) + (i), \
(vec) + (i) + 1, \
sizeof(*(vec)) * (cv_sz__ - 1 - (i))); \
Expand Down Expand Up @@ -264,7 +281,7 @@ typedef struct cvector_metadata_t {
cvector_grow((vec), cvector_compute_next_grow(cv_cap__)); \
} \
if ((pos) < cvector_size(vec)) { \
memmove( \
cvector_clib_memmove( \
(vec) + (pos) + 1, \
(vec) + (pos), \
sizeof(*(vec)) * ((cvector_size(vec)) - (pos))); \
Expand Down Expand Up @@ -298,10 +315,26 @@ typedef struct cvector_metadata_t {
if ((from)) { \
cvector_grow(to, cvector_size(from)); \
cvector_set_size(to, cvector_size(from)); \
memcpy((to), (from), cvector_size(from) * sizeof(*(from))); \
cvector_clib_memcpy((to), (from), cvector_size(from) * sizeof(*(from))); \
} \
} while (0)

/**
* @brief cvector_swap - exchanges the content of the vector by the content of another vector of the same type
* @param vec - the original vector
* @param other - the other vector to swap content with
* @param type - the type of both vectors
* @return void
*/
#define cvector_swap(vec, other, type) \
do { \
if (vec && other) { \
cvector_vector_type(type) cv_swap__ = vec; \
vec = other; \
other = cv_swap__; \
} \
} while (0)

/**
* @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector
* @param vec - the vector
Expand Down Expand Up @@ -354,16 +387,29 @@ typedef struct cvector_metadata_t {
if (vec) { \
void *cv_p1__ = cvector_vec_to_base(vec); \
void *cv_p2__ = cvector_clib_realloc(cv_p1__, cv_sz__); \
assert(cv_p2__); \
cvector_clib_assert(cv_p2__); \
(vec) = cvector_base_to_vec(cv_p2__); \
} else { \
void *cv_p__ = cvector_clib_malloc(cv_sz__); \
assert(cv_p__); \
cvector_clib_assert(cv_p__); \
(vec) = cvector_base_to_vec(cv_p__); \
cvector_set_size((vec), 0); \
cvector_set_elem_destructor((vec), NULL); \
} \
cvector_set_capacity((vec), (count)); \
} while (0)

/**
* @brief cvector_shrink_to_fit - requests the container to reduce its capacity to fit its size
* @param vec - the vector
* @return void
*/
#define cvector_shrink_to_fit(vec) \
do { \
if (vec) { \
const size_t cv_sz___ = cvector_size(vec); \
cvector_grow(vec, cv_sz___); \
} \
} while (0)

#endif /* CVECTOR_H_ */
2 changes: 1 addition & 1 deletion example.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) {

/* iterator over the vector using "iterator" style */
if (v) {
int *it;
cvector_iterator(int) it;
int i = 0;
for (it = cvector_begin(v); it != cvector_end(v); ++it) {
printf("v[%d] = %d\n", i, *it);
Expand Down
2 changes: 1 addition & 1 deletion test.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int main() {

/* iterator over the vector using "iterator" style */
if (v) {
int *it;
cvector_iterator(int) it;
int i = 0;
for (it = cvector_begin(v); it != cvector_end(v); ++it) {
printf("v[%d] = %d\n", i, *it);
Expand Down
47 changes: 45 additions & 2 deletions unit-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ UTEST(test, vector_iterator) {

/* iterator over the vector using "iterator" style */
if (v) {
int *it;
cvector_iterator(int) it;
int i = 0;
for (it = cvector_begin(v); it != cvector_end(v); ++it) {
switch (i) {
Expand Down Expand Up @@ -143,6 +143,33 @@ UTEST(test, vector_copy) {
cvector_free(b);
}

UTEST(test, vector_swap) {
cvector_vector_type(int) a = NULL;
cvector_vector_type(int) b = NULL;

cvector_push_back(a, 1);
cvector_push_back(a, 2);
cvector_push_back(a, 3);

cvector_push_back(b, 4);
cvector_push_back(b, 5);
cvector_push_back(b, 6);
cvector_push_back(b, 7);

ASSERT_EQ(cvector_size(a), (size_t)3);
ASSERT_EQ(cvector_size(b), (size_t)4);

cvector_swap(a, b, int);

ASSERT_EQ(cvector_size(a), (size_t)4);
ASSERT_EQ(cvector_size(b), (size_t)3);

ASSERT_EQ(a[0], 4);
ASSERT_EQ(a[1], 5);
ASSERT_EQ(b[0], 1);
ASSERT_EQ(b[1], 2);
}

UTEST(test, vector_reserve) {
int i;
cvector_vector_type(int) c = NULL;
Expand Down Expand Up @@ -182,7 +209,7 @@ UTEST(test, vector_free_all) {
}

UTEST(test, vector_for_each_int) {
char **it;
cvector_iterator(char *) it;
int i;
cvector_vector_type(char *) v = NULL;
for (i = 0; i < 10; ++i) {
Expand All @@ -201,6 +228,22 @@ UTEST(test, vector_for_each_int) {
cvector_free_each_and_free(v, free);
}

UTEST(test, vector_shrink_to_fit) {
cvector_vector_type(int) a = NULL;

cvector_push_back(a, 1);
cvector_push_back(a, 5);
cvector_push_back(a, 4);

cvector_reserve(a, 50);
ASSERT_EQ(cvector_capacity(a), (size_t)50);

cvector_shrink_to_fit(a);
ASSERT_EQ(cvector_capacity(a), (size_t)3);

cvector_free(a);
}

struct data_t {
int num;
int a, b, c, d;
Expand Down

0 comments on commit 576e5ec

Please sign in to comment.