Code Monkey home page Code Monkey logo

vec's Introduction

vec

A type-safe dynamic array implementation for C.

Installation

The vec.c and vec.h files can be dropped into an existing C project and compiled along with it.

Usage

Before using a vector it should first be initialised using the vec_init() function.

vec_int_t v;
vec_init(&v);
vec_push(&v, 123);
vec_push(&v, 456);

To access the elements of the vector directly the vector's data field can be used.

printf("%d\n", v.data[1]); /* Prints the value at index 1 */

The current length of the vector is stored in the length field of the vector

printf("%d\n", v.length); /* Prints the length of the vector */

When you are done with the vector the vec_deinit() function should be called on it. This will free any memory the vector allocated during use.

vec_deinit(&v);

Types

vec.h provides the following predefined vector types:

Contained Type Type name
void* vec_void_t
char* vec_str_t
int vec_int_t
char vec_char_t
float vec_float_t
double vec_double_t

To define a new vector type the vec_t() macro should be used:

/* Creates the type uint_vec_t for storing unsigned ints */
typedef vec_t(unsigned int) uint_vec_t;

Functions

All vector functions are macro functions. The parameter v in each function should be a pointer to the vec struct which the operation is to be performed on.

vec_t(T)

Creates a vec struct for containing values of type T.

/* Typedefs the struct `fp_vec_t` as a container for type FILE* */
typedef vec_t(FILE*) fp_vec_t;

vec_init(v)

Initialises the vector, this must be called before the vector can be used.

vec_deinit(v)

Deinitialises the vector, freeing the memory the vector allocated during use; this should be called when we're finished with a vector.

vec_push(v, val)

Pushes a value to the end of the vector. Returns 0 if the operation was successful, otherwise -1 is returned and the vector remains unchanged.

vec_pop(v)

Removes and returns the value at the end of the vector.

vec_splice(v, start, count)

Removes the number of values specified by count, starting at the index start.

vec_splice(&v, 2, 4); /* Removes the values at indices 2, 3, 4 and 5 */

vec_swapsplice(v, start, count)

Removes the number of values specified by count, starting at the index start; the removed values are replaced with the last count values of the vector. This does not preserve ordering but is O(1).

vec_insert(v, idx, val)

Inserts the value val at index idx shifting the elements after the index to make room for the new value.

/* Inserts the value 123 at the beginning of the vec */
vec_insert(&v, 0, 123);

Returns 0 if the operation was successful, otherwise -1 is returned and the vector remains unchanged.

vec_sort(v, fn)

Sorts the values of the vector; fn should be a qsort-compatible compare function.

vec_swap(v, idx1, idx2)

Swaps the values at the indices idx1 and idx2 with one another.

vec_truncate(v, len)

Truncates the vector's length to len. If len is greater than the vector's current length then no change is made.

vec_clear(v)

Clears all values from the vector reducing the vector's length to 0.

vec_first(v)

Returns the first value in the vector. This should not be used on an empty vector.

vec_last(v)

Returns the last value in the vector. This should not be used on an empty vector.

vec_reserve(v, n)

Reserves capacity for at least n elements in the given vector; if n is less than the current capacity then vec_reserve() does nothing. Returns 0 if the operation was successful, otherwise -1 is returned and the vector remains unchanged.

vec_compact(v)

Reduces the vector's capacity to the smallest size required to store its current number of values. Returns 0 if the operation is successful, otherwise -1 is returned and the vector remains unchanged.

vec_pusharr(v, arr, count)

Pushes the contents of the array arr to the end of the vector. count should be the number of elements in the array.

vec_extend(v, v2)

Appends the contents of the v2 vector to the v vector.

vec_find(v, val, idx)

Finds the first occurrence of the value val in the vector. idx should be an int where the value's index will be written; idx is set to -1 if val could not be found in the vector.

vec_remove(v, val)

Removes the first occurrence of the value val from the vector. If the val is not contained in the vector then vec_remove() does nothing.

vec_reverse(v)

Reverses the order of the vector's values in place. For example, a vector containing 4, 5, 6 would contain 6, 5, 4 after reversing.

vec_foreach(v, var, iter)

Iterates the values of the vector from the first to the last. var should be a variable of the vector's contained type where the value will be stored with each iteration. iter should be an int used to store the index during iteration.

/* Iterates and prints the value and index of each value in the float vec */
int i; float val;
vec_foreach(&v, val, i) {
  printf("%d : %f\n", i, val);
}

vec_foreach_rev(v, var, iter)

Iterates the values of the vector from the last to the first. See vec_foreach()

vec_foreach_ptr(v, var, iter)

Iterates the value pointers of the vector from first to last. var should be a variable of the vector's contained type's pointer. See vec_foreach().

/* Iterates and prints the value and index of each value in the float vector */
int i; float *val;
vec_foreach_ptr(&v, val, i) {
  printf("%d : %f\n", i, *val);
}

vec_foreach_ptr_rev(v, var, iter)

Iterates the value pointers of the vector from last to first. See vec_foreach_ptr()

License

This library is free software; you can redistribute it and/or modify it under the terms of the MIT license. See LICENSE for details.

vec's People

Contributors

rxi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vec's Issues

Tag releases

Could you please add tags for your releases? This way it becomes easier to use your component as git submodule.

Custom Memory Allocator Support

I am unsure if this project is still actively maintained, though I thought I would create the issue as it is still used in code today.

I wanted to propose the addition of support for custom memory allocation and freeing, just a simple set of macros (i.e. VEC_MALLOC, VEC_FREE, etc.). When such macros are defined, the library will use them in place of the default ones.

It is obviously trivial for users to add this behavior themselves with a few quick find/replace in the editor, I just thought it would be a nice feature to have out of the box that could be easily added without too much effort.

If you are willing to accept pull-requests, I would be happy to issue one for it. Either way, thank you for sharing :)

vec_-functions induce UB

#define vec_unpack_(v)\
    (char**)&(v)->data, &(v)->length, &(v)->capacity, sizeof(*(v)->data)

Strictly speaking, (char**)&(v)->data is only correctly defined when data actually is a char-pointer, elsewise dereferencing this pointer in your functions causes undefined behaviour.

Wrong value if used in a for loop

Below is the code:

    vec_void_t v;
    vec_init(&v);

    int i, j, m, n;

    i = 1;
    vec_push(&v, &i);

    j = 2;
    vec_push(&v, &j);

    m = 3;
    vec_push(&v, &m);

    n = 4;
    vec_push(&v, &n);

    for (i = 0; i < 4; i++) {
        printf("v[%d] = %d\n", i, *(int *)v.data[i]);
    }
    vec_deinit(&v);

The result is:

v[0] = 0
v[1] = 2
v[2] = 3
v[3] = 4

The expected result should be:

v[0] = 1
v[1] = 2
v[2] = 3
v[3] = 4

if I change the for-loop to below code:

    printf("v[0] = %d\n", *(int *)v.data[0]);
    printf("v[1] = %d\n", *(int *)v.data[1]);
    printf("v[2] = %d\n", *(int *)v.data[2]);
    printf("v[3] = %d\n", *(int *)v.data[3]);

Then, the result is expected.

Return success values for vec_pusharr and vec_extend

Since both of these functions are implemented as do-while macros (through vec_pusharr), there's no way of knowing if the reallocs in them succeeded or not, which is bad. Returning a 0 or -1 like the rest of the functions would be good.

vec_insert() problem happens again

Hi, when I use vec_insert(), I meet the problem of "right-hand operand of comma expression has no effect" again, even if I have revised vec.h in the way mentioned in another issue. It shows the following problem:
In file included from src/crawler.c:19:0:
src/crawler.c: In function 'getHTML':
./include/vec.h:54:43: warning: pointer/integer type mismatch in conditional expression
( vec_insert_(vec_unpack_(v), idx) ? -1 :
^
./include/vec.h:54:43: note: in definition of macro 'vec_insert'
( vec_insert_(vec_unpack_(v), idx) ? -1 :
^~
((v)->data[idx] = (val)), (v)->length++, 0 )

./include/vec.h:55:44: warning: right-hand operand of comma expression has no effect [-Wunused-value]
( vec_insert_(vec_unpack_(v), idx) ? -1 :\

  ((v)->data[idx] = (val)), (v)->length++, 0 )
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
src/crawler.c:558:17: note: in expansion of macro 'vec_insert'
              vec_insert(url_vec, 0, whole);
              ^~~~~~~~~~
./include/vec.h:54:43: warning: pointer/integer type mismatch in conditional expression
( vec_insert_(vec_unpack_(v), idx) ? -1 :\
                                        ^
./include/vec.h:54:43: note: in definition of macro 'vec_insert'
( vec_insert_(vec_unpack_(v), idx) ? -1 :\
                                        ^~
  ((v)->data[idx] = (val)), (v)->length++, 0 )
                                         
./include/vec.h:55:44: warning: right-hand operand of comma expression has no effect [-Wunused-value]
( vec_insert_(vec_unpack_(v), idx) ? -1 :\
 ((v)->data[idx] = (val)), (v)->length++, 0 )
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~

src/crawler.c:567:17: note: in expansion of macro 'vec_insert'
vec_insert(url_vec, 0, whole);
^~~~~~~~~~

Please revise the vec.h, thanks

Error: right-hand operand of comma expression has no effect

Hi. Thanks for sharing your project!

I get the following error while compiling with the xtensa-esp32-elf tool chain for the Espressif ESP32 platform:

#define vec_push(v, val)\
  ( vec_expand_(vec_unpack_(v)) ? -1 :\
    ((v)->data[(v)->length++] = (val), 0), 0 )

Error: right-hand operand of comma expression has no effect [-Werror=unused-value]

I can't start my program anymore. Any idea how to solve this issue?


I started a discussion about the issue described above on stackoverflow.com. I received great input, please take a look here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.