Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,49 @@ Some functions and macros take a normal vector argument, e.g. `vec`, while other
| reserve space for 255 items in `vec` | `vector_reserve(&vec, 255);` | yes |
| make a copy of `vec` | `type* vec_copy = vector_copy(vec);` | no |

# Convenience Iterator and Access Macros

Several macros are implemented to make iteration and element access more convenient

### `vector_front(vec)`

Access the first element in the vector by value (`vec[0]`).

Will cause an out-of-bounds access on an empty vector.

### `vector_back(vec)`

Access the last element in the vector by value (`vec[vector_size(vec) - 1]`).

Will cause an out-of-bounds access on an empty vector.

### `vector_begin(vec)`

Address of first element in vector (`vec`).

### `vector_end(vec)`

Address of element "past the end" of the vector. (`vec + vector_size(vec)`).

### `vector_foreach(*T, vec)`

Iterate over the vector using the provided item pointer.

```c
int *int_vec = vector_create();

for (size_t i = 0; i < 100; i += 1) {
vector_add(&int_vec, i);
}

int sum = 0;
vector_foreach(int *ip, int_vec) {
sum += *ip;
}

printf ("The sum of items is %d", sum);
```

# Missing typeof Reference Sheet

Because some compilers don't support the `typeof` operator, which is used for static type checks in some of this library's macros, you have to use a slightly different set of macros. Unfortunately, this also means some errors will be missed at compile time, so if you're getting runtime errors, make sure you are properly using `vec` and `&vec` for their corresponding calls.
Expand All @@ -166,4 +209,4 @@ Because some compilers don't support the `typeof` operator, which is used for st
| erase `4` items from `vec` at index `3` | `vector_erase(vec, type, 3, 4);` | no (moves elements) |
| remove item at index `3` from `vec` | `vector_remove(vec, type, 3);` | no (moves elements) |
| add `item` to the vector `vec` | `type* temp = vector_add_dst(&vec, type);` | yes |
| insert `item` into `vec` at index `9` | `type* temp = vector_insert_dst(&vec, type, 9);` | yes |
| insert `item` into `vec` at index `9` | `type* temp = vector_insert_dst(&vec, type, 9);` | yes |
34 changes: 33 additions & 1 deletion vec.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ vector_header* vector_get_header(vector vec) { return &((vector_header*)vec)[-1]

vector vector_create(void)
{
vector_header* h = (vector_header*)malloc(sizeof(vector_header));
vector_header* h = malloc(sizeof(vector_header));
if (!h)
{
return NULL;
}
h->capacity = 0;
h->size = 0;

Expand All @@ -61,6 +65,10 @@ vector_header* vector_realloc(vector_header* h, vec_type_t type_size)
{
vec_size_t new_capacity = (h->capacity == 0) ? 1 : h->capacity * 2;
vector_header* new_h = (vector_header*)realloc(h, sizeof(vector_header) + new_capacity * type_size);
if (!new_h)
{
return NULL;
}
new_h->capacity = new_capacity;

return new_h;
Expand All @@ -78,6 +86,11 @@ void* _vector_add_dst(vector* vec_addr, vec_type_t type_size)
if (!vector_has_space(h))
{
h = vector_realloc(h, type_size);
if (!h)
{
*vec_addr = NULL;
return NULL;
}
*vec_addr = h->data;
}

Expand All @@ -94,6 +107,11 @@ void* _vector_insert_dst(vector* vec_addr, vec_type_t type_size, vec_size_t pos)
if (!vector_has_space(h))
{
h = vector_realloc(h, type_size);
if (!h)
{
*vec_addr = NULL;
return NULL;
}
*vec_addr = h->data;
}
// move trailing elements
Expand All @@ -116,6 +134,11 @@ void _vector_erase(vector vec, vec_type_t type_size, vec_size_t pos, vec_size_t
h->size -= len;
}

void vector_clear(vector vec) {
vector_header* h = vector_get_header(vec);
h->size = 0;
}

void _vector_remove(vector vec, vec_type_t type_size, vec_size_t pos)
{
_vector_erase(vec, type_size, pos, 1);
Expand All @@ -132,6 +155,11 @@ void _vector_reserve(vector* vec_addr, vec_type_t type_size, vec_size_t capacity
}

h = (vector_header*)realloc(h, sizeof(vector_header) + capacity * type_size);
if (!h)
{
*vec_addr = NULL;
return;
}
h->capacity = capacity;
*vec_addr = &h->data;
}
Expand All @@ -141,6 +169,10 @@ vector _vector_copy(vector vec, vec_type_t type_size)
vector_header* h = vector_get_header(vec);
size_t alloc_size = sizeof(vector_header) + h->size * type_size;
vector_header* copy_h = (vector_header*)malloc(alloc_size);
if (!copy_h)
{
return NULL;
}
memcpy(copy_h, h, alloc_size);
copy_h->capacity = copy_h->size;

Expand Down
29 changes: 25 additions & 4 deletions vec.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifdef __cplusplus
extern "C" {

#endif

#include <stdbool.h>
#include <stdlib.h>

// generic type for internal use
typedef void* vector;
typedef void *vector;
// number of elements in a vector
typedef size_t vec_size_t;
// number of bytes for a type
Expand Down Expand Up @@ -97,28 +98,48 @@ typedef size_t vec_type_t;
#define vector_copy(vec)\
(_vector_copy((vector)vec, sizeof(*vec)))

/*
* Convenience macros for iteration and access
*/

// Get last element in vector by value (warning--vector may be empty!)
#define vector_back(vec) (vec[vector_size(vec) - 1])

// Get pointer to object past end of vector for iterator use
#define vector_end(vec) (vec + vector_size(vec))

// Get first element in vector by value (warning--vector may be empty!)
#define vector_front(vec) (vec[0])

#define vector_begin(vec) (vec)

#define vector_foreach(item, vec) for(int _cont = 1, _count = 0; _cont && _count < vector_size(vec); _cont = 1, _count += 1) \
for (item = vector_begin(vec) + _count; _cont; _cont = 0)

vector vector_create(void);

void vector_free(vector vec);

void* _vector_add_dst(vector* vec_addr, vec_type_t type_size);
void *_vector_add_dst(vector *vec_addr, vec_type_t type_size);

void* _vector_insert_dst(vector* vec_addr, vec_type_t type_size, vec_size_t pos);
void *_vector_insert_dst(vector *vec_addr, vec_type_t type_size, vec_size_t pos);

void _vector_erase(vector vec_addr, vec_type_t type_size, vec_size_t pos, vec_size_t len);

void _vector_remove(vector vec_addr, vec_type_t type_size, vec_size_t pos);

void vector_pop(vector vec);

void _vector_reserve(vector* vec_addr, vec_type_t type_size, vec_size_t capacity);
void _vector_reserve(vector *vec_addr, vec_type_t type_size, vec_size_t capacity);

vector _vector_copy(vector vec, vec_type_t type_size);

vec_size_t vector_size(vector vec);

vec_size_t vector_capacity(vector vec);

void vector_clear(vector vec);

// closing bracket for extern "C"
#ifdef __cplusplus
}
Expand Down