├── LICENSE
├── README.md
├── cvec.c
└── cvec.h
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cvec
2 |
3 | A no bullshit type-safe vector library for C that supports operator `[]` for
4 | indexing.
5 |
6 | ## Example
7 | ```c
8 | #include "cvec.h"
9 |
10 | int *x = NULL; /* initialize to NULL, replace *int* with any type you want */
11 |
12 | vector_push(x, 100);
13 | vector_push(x, 200);
14 | vector_push(x, 300);
15 |
16 | /* standard [] lookup of values */
17 | printf("%d, %d, %d", x[0], x[1], x[2]);
18 |
19 | /* free memory */
20 | vector_free(x);
21 | ```
22 |
23 | ## How it works
24 | Metadata of a vector is stored as a header behind the pointer exactly
25 | `sizeof(vector_t)` behind. This is how operator `[]` can still be used for
26 | indexing. Type safety is provided by having the pointer encode the type
27 | via the language itself. No strange `void*` tricks. Though the generic resize
28 | functions sort of cast to `void*` but that is standard practice in C.
29 |
30 | ## API
31 |
32 | Note that `VECTOR` is any pointer type and that the API is mostly implemented
33 | using macros. The macros all take `VECTOR` argument, size and indexing
34 | arguments are expected to be `size_t`. The macros which push back a value
35 | expect the pointer's base type.
36 |
37 | ##### vector_try_grow(VECTOR, MORE)
38 | Attempts to grow `VECTOR` by `MORE`
39 |
40 | ##### vector_meta(VECTOR)
41 | Get the metadata block for `VECTOR`
42 |
43 | ##### vector_free(VECTOR)
44 | Deletes `VECTOR` and sets it to `NULL`
45 |
46 | ##### vector_push(VECTOR, VALUE)
47 | Pushes back `VALUE` into `VECTOR`
48 |
49 | ##### vector_size(VECTOR)
50 | Get the size of `VECTOR`
51 |
52 | ##### vector_capacity(VECTOR)
53 | Get the capacity of `VECTOR`
54 |
55 | ##### vector_resize(VECTOR, SIZE)
56 | Resize `VECTOR` to accomodate `SIZE` more elements
57 |
58 | ##### vector_last(VECTOR)
59 | Get the last element in `VECTOR`
60 |
61 | ##### vector_pop(VECTOR)
62 | Pop an element off the back of `VECTOR`
63 |
64 | ##### vector_shrinkto(VECTOR, SIZE)
65 | Shrink the size of `VECTOR` down to `SIZE`
66 |
67 | ##### vector_shrinkby(VECTOR, AMOUNT)
68 | Shrink `VECTOR` down by `AMOUNT`
69 |
70 | ##### vector_append(VECTOR, COUNT, POINTER)
71 | Append to `VECTOR`, `COUNT` elements from `POINTER`
72 |
73 | ##### vector_remove(VECTOR, INDEX, COUNT)
74 | Remove from `VECTOR`, `COUNT` elements starting from `INDEX`
75 |
--------------------------------------------------------------------------------
/cvec.c:
--------------------------------------------------------------------------------
1 | #include "cvec.h"
2 |
3 | void vec_grow(void **vector, size_t more, size_t type_size) {
4 | vector_t *meta = vector_meta(*vector);
5 | size_t count = 0;
6 | void *data = NULL;
7 |
8 | if (*vector) {
9 | count = 2 * meta->allocated + more;
10 | data = realloc(meta, type_size * count + sizeof *meta);
11 | } else {
12 | count = more + 1;
13 | data = malloc(type_size * count + sizeof *meta);
14 | ((vector_t *)data)->used = 0;
15 | }
16 |
17 | meta = (vector_t *)data;
18 | meta->allocated = count;
19 | *vector = meta + 1;
20 | }
21 |
22 | void vec_delete(void *vector) {
23 | free(vector_meta(vector));
24 | }
25 |
--------------------------------------------------------------------------------
/cvec.h:
--------------------------------------------------------------------------------
1 | #ifndef CVEC_HDR
2 | #define CVEC_HDR
3 | #include
4 | #include
5 |
6 | typedef struct {
7 | size_t allocated;
8 | size_t used;
9 | } vector_t;
10 |
11 |
12 | /* Attempts to grow [VECTOR] by [MORE]*/
13 | #define vector_try_grow(VECTOR, MORE) \
14 | (((!(VECTOR) || vector_meta(VECTOR)->used + (MORE) >= vector_meta(VECTOR)->allocated)) ? \
15 | (void)vec_grow(((void **)&(VECTOR)), (MORE), sizeof(*(VECTOR))) : (void)0)
16 |
17 | /* Get the metadata block for [VECTOR] */
18 | #define vector_meta(VECTOR) \
19 | ((vector_t *)(((unsigned char *)(VECTOR)) - sizeof(vector_t)))
20 |
21 | /* Deletes [VECTOR] and sets it to NULL */
22 | #define vector_free(VECTOR) \
23 | ((void)((VECTOR) ? (vec_delete((void *)(VECTOR)), (VECTOR) = NULL) : 0))
24 |
25 | /* Pushes back [VALUE] into [VECTOR] */
26 | #define vector_push(VECTOR, VALUE) \
27 | (vector_try_grow((VECTOR), 1), (VECTOR)[vector_meta(VECTOR)->used++] = (VALUE))
28 |
29 | /* Get the size of [VECTOR] */
30 | #define vector_size(VECTOR) \
31 | ((VECTOR) ? vector_meta(VECTOR)->used : 0)
32 |
33 | /* Get the capacity of [VECTOR] */
34 | #define vector_capacity(VECTOR) \
35 | ((VECTOR) ? vector_meta(VECTOR)->allocated : 0)
36 |
37 | /* Resize [VECTOR] to accomodate [SIZE] more elements */
38 | #define vector_resize(VECTOR, SIZE) \
39 | (vector_try_grow((VECTOR), (SIZE)), vector_meta(VECTOR)->used += (SIZE), \
40 | &(VECTOR)[vector_meta(VECTOR)->used - (SIZE)])
41 |
42 | /* Get the last element in [VECTOR] */
43 | #define vector_last(VECTOR) \
44 | ((VECTOR)[vector_meta(VECTOR)->used - 1])
45 |
46 | /* Pop an element off the back of [VECTOR] */
47 | #define vector_pop(VECTOR) \
48 | ((void)(vector_meta(VECTOR)->used -= 1))
49 |
50 | /* Shrink the size of [VECTOR] down to [SIZE] */
51 | #define vector_shrinkto(VECTOR, SIZE) \
52 | ((void)(vector_meta(VECTOR)->used = (SIZE)))
53 |
54 | /* Shrink [VECTOR] down by [AMOUNT] */
55 | #define vector_shrinkby(VECTOR, AMOUNT) \
56 | ((void)(vector_meta(VECTOR)->used -= (AMOUNT)))
57 |
58 | /* Append to [VECTOR], [COUNT] elements from [POINTER] */
59 | #define vector_append(VECTOR, COUNT, POINTER) \
60 | ((void)(memcpy(vector_resize((VECTOR), (COUNT)), (POINTER), (COUNT) * sizeof(*(POINTER)))))
61 |
62 | /* Remove from [VECTOR], [COUNT] elements starting from [INDEX] */
63 | #define vector_remove(VECTOR, INDEX, COUNT) \
64 | ((void)(memmove((VECTOR) + (INDEX), (VECTOR) + (INDEX) + (COUNT), \
65 | sizeof(*(VECTOR)) * (vector_meta(VECTOR)->used - (INDEX) - (COUNT))), \
66 | vector_meta(VECTOR)->used -= (COUNT)))
67 |
68 | void vec_grow(void **vector, size_t i, size_t s);
69 | void vec_delete(void *vector);
70 |
71 | #endif
72 |
--------------------------------------------------------------------------------