From 13e5c9f8b6ca97641fd2f2fe15b7233dd25c6ccb Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Wed, 2 Jan 2019 17:25:53 +0100 Subject: [PATCH] work on parenthesis --- grammar/grammar.py | 12 ++-- include/siri/db/queries.h | 7 +- include/siri/db/sset.h | 20 ++++++ include/siri/grammar/grammar.h | 5 +- include/vec/vec.h | 2 + src/siri/db/listener.c | 125 ++++++++++++++++++++------------- src/siri/db/queries.c | 27 ++++--- src/siri/db/sset.c | 42 +++++++++++ src/siri/grammar/grammar.c | 43 ++++++++---- src/vec/vec.c | 13 ++++ 10 files changed, 213 insertions(+), 83 deletions(-) create mode 100644 include/siri/db/sset.h create mode 100644 src/siri/db/sset.c diff --git a/grammar/grammar.py b/grammar/grammar.py index 5f6d96ff..96a48905 100644 --- a/grammar/grammar.py +++ b/grammar/grammar.py @@ -407,28 +407,32 @@ class SiriGrammar(Grammar): Sequence(THIS, k_and, THIS), Sequence(THIS, k_or, THIS))) - series_sep = Choice( + series_setopr = Choice( k_union, c_difference, k_intersection, k_symmetric_difference, most_greedy=False) + series_parenthesis = Sequence('(', THIS, ')') + series_all = Choice(Token('*'), k_all, most_greedy=False) series_name = Repeat(string, 1, 1) group_name = Repeat(r_grave_str, 1, 1) series_re = Repeat(r_regex, 1, 1) uuid = Choice(r_uuid_str, string, most_greedy=False) group_match = Repeat(r_grave_str, 1, 1) - series_match = List( + series_match = Prio( Choice( series_all, series_name, group_match, series_re, most_greedy=False), - series_sep, - 1) + Sequence(THIS, series_setopr, THIS), + series_parenthesis + ) + limit_expr = Sequence(k_limit, int_expr) before_expr = Sequence(k_before, time_expr) diff --git a/include/siri/db/queries.h b/include/siri/db/queries.h index d47c5c42..324448da 100644 --- a/include/siri/db/queries.h +++ b/include/siri/db/queries.h @@ -42,11 +42,12 @@ typedef enum #define QUERY_DEF \ uint8_t tp; \ uint8_t flags; \ -imap_t * series_map; \ +imap_t ** series_mapp; \ imap_t * series_tmp; \ imap_t * pmap; \ -vec_t * vec; \ -size_t vec_index; \ +vec_t * series_vec; \ +vec_t * vec; \ +size_t vec_index; \ imap_update_cb update_cb; \ cexpr_t * where_expr; \ pcre2_code * regex; \ diff --git a/include/siri/db/sset.h b/include/siri/db/sset.h new file mode 100644 index 00000000..226232cc --- /dev/null +++ b/include/siri/db/sset.h @@ -0,0 +1,20 @@ +/* + * sset.h - Set operations on series. + */ +#ifndef SIRIDB_SSET_H_ +#define SIRIDB_SSET_H_ + +typedef struct siridb_sset_s siridb_sset_t; + +#include + +siridb_sset_t * siridb_sset_new(void); +void siridb_sset_free(siridb_sset_t * sset); + +struct siridb_sset_s +{ + imap_t * series_map; + imap_update_cb update_cb; +}; + +#endif /* SIRIDB_SSET_H_ */ diff --git a/include/siri/grammar/grammar.h b/include/siri/grammar/grammar.h index 45b8a8b2..f5ca0053 100644 --- a/include/siri/grammar/grammar.h +++ b/include/siri/grammar/grammar.h @@ -5,7 +5,7 @@ * should be used with the libcleri module. * * Source class: SiriGrammar - * Created at: 2018-10-29 10:52:57 + * Created at: 2019-01-02 15:54:36 */ #ifndef CLERI_EXPORT_SIRI_GRAMMAR_GRAMMAR_H_ #define CLERI_EXPORT_SIRI_GRAMMAR_GRAMMAR_H_ @@ -275,8 +275,9 @@ enum cleri_grammar_ids { CLERI_GID_SERIES_COLUMNS, CLERI_GID_SERIES_MATCH, CLERI_GID_SERIES_NAME, + CLERI_GID_SERIES_PARENTHESIS, CLERI_GID_SERIES_RE, - CLERI_GID_SERIES_SEP, + CLERI_GID_SERIES_SETOPR, CLERI_GID_SERVER_COLUMNS, CLERI_GID_SET_ADDRESS, CLERI_GID_SET_BACKUP_MODE, diff --git a/include/vec/vec.h b/include/vec/vec.h index 9600bea6..31b769a5 100644 --- a/include/vec/vec.h +++ b/include/vec/vec.h @@ -8,12 +8,14 @@ typedef struct vec_s vec_t; typedef struct vec_object_s vec_object_t; +typedef void (*vec_destroy_cb)(void *); #include #include #include vec_t * vec_new(size_t size); +void vec_destroy(vec_t * vec, vec_destroy_cb cb); vec_t * vec_copy(vec_t * source); void vec_compact(vec_t ** vec); int vec_append_safe(vec_t ** vec, void * data); diff --git a/src/siri/db/listener.c b/src/siri/db/listener.c index ea5600b4..8588d574 100644 --- a/src/siri/db/listener.c +++ b/src/siri/db/listener.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -201,8 +202,9 @@ static void enter_set_password(uv_async_t * handle); static void enter_series_all(uv_async_t * handle); static void enter_series_name(uv_async_t * handle); static void enter_series_match(uv_async_t * handle); +static void enter_series_parenthesis(uv_async_t * handle); static void enter_series_re(uv_async_t * handle); -static void enter_series_sep(uv_async_t * handle); +static void enter_series_setopr(uv_async_t * handle); static void enter_timeit_stmt(uv_async_t * handle); static void enter_where_xxx(uv_async_t * handle); static void enter_xxx_columns(uv_async_t * handle); @@ -242,6 +244,7 @@ static void exit_revoke_user(uv_async_t * handle); static void exit_select_aggregate(uv_async_t * handle); static void exit_select_stmt(uv_async_t * handle); static void exit_series_match(uv_async_t * handle); +static void exit_series_parenthesis(uv_async_t * handle); static void exit_set_address(uv_async_t * handle); static void exit_set_backup_mode(uv_async_t * handle); static void exit_set_drop_threshold(uv_async_t * handle); @@ -428,8 +431,9 @@ void siridb_init_listener(void) siridb_listen_enter[CLERI_GID_SERIES_ALL] = enter_series_all; siridb_listen_enter[CLERI_GID_SERIES_NAME] = enter_series_name; siridb_listen_enter[CLERI_GID_SERIES_MATCH] = enter_series_match; + siridb_listen_enter[CLERI_GID_SERIES_PARENTHESIS] = enter_series_parenthesis; siridb_listen_enter[CLERI_GID_SERIES_RE] = enter_series_re; - siridb_listen_enter[CLERI_GID_SERIES_SEP] = enter_series_sep; + siridb_listen_enter[CLERI_GID_SERIES_SETOPR] = enter_series_setopr; siridb_listen_enter[CLERI_GID_SHARD_COLUMNS] = enter_xxx_columns; siridb_listen_enter[CLERI_GID_TIMEIT_STMT] = enter_timeit_stmt; siridb_listen_enter[CLERI_GID_USER_COLUMNS] = enter_xxx_columns; @@ -475,6 +479,7 @@ void siridb_init_listener(void) siridb_listen_exit[CLERI_GID_SELECT_AGGREGATE] = exit_select_aggregate; siridb_listen_exit[CLERI_GID_SELECT_STMT] = exit_select_stmt; siridb_listen_exit[CLERI_GID_SERIES_MATCH] = exit_series_match; + siridb_listen_exit[CLERI_GID_SERIES_PARENTHESIS] = exit_series_parenthesis; siridb_listen_exit[CLERI_GID_SET_ADDRESS] = exit_set_address; siridb_listen_exit[CLERI_GID_SET_BACKUP_MODE] = exit_set_backup_mode; siridb_listen_exit[CLERI_GID_SET_DROP_THRESHOLD] = exit_set_drop_threshold; @@ -804,7 +809,7 @@ static void enter_group_match(uv_async_t * handle) size_t i; q_wrapper->series_tmp = (q_wrapper->update_cb == NULL) ? - q_wrapper->series_map : imap_new(); + *q_wrapper->series_mapp : imap_new(); if (q_wrapper->series_tmp == NULL) { @@ -829,7 +834,7 @@ static void enter_group_match(uv_async_t * handle) if (q_wrapper->update_cb != NULL) { (*q_wrapper->update_cb)( - q_wrapper->series_map, + *q_wrapper->series_mapp, q_wrapper->series_tmp, (imap_free_cb) &siridb__series_decref); } @@ -1203,12 +1208,12 @@ static void enter_series_name(uv_async_t * handle) if (q_wrapper->update_cb == &imap_intersection_ref) { imap_free( - q_wrapper->series_map, + *q_wrapper->series_mapp, (imap_free_cb) &siridb__series_decref); - q_wrapper->series_map = imap_new(); + *q_wrapper->series_mapp = imap_new(); - if (q_wrapper->series_map == NULL) + if (*q_wrapper->series_mapp == NULL) { MEM_ERR_RET } @@ -1219,7 +1224,7 @@ static void enter_series_name(uv_async_t * handle) if ( q_wrapper->update_cb == NULL || q_wrapper->update_cb == &imap_union_ref) { - if (imap_set(q_wrapper->series_map, series->id, series) == 1) + if (imap_set(*q_wrapper->series_mapp, series->id, series) == 1) { siridb_series_incref(series); } @@ -1227,7 +1232,7 @@ static void enter_series_name(uv_async_t * handle) else if (q_wrapper->update_cb == &imap_difference_ref) { series = (siridb_series_t *) imap_pop( - q_wrapper->series_map, + *q_wrapper->series_mapp, series->id); if (series != NULL) { @@ -1237,7 +1242,7 @@ static void enter_series_name(uv_async_t * handle) else if (q_wrapper->update_cb == &imap_intersection_ref) { series = (siridb_series_t *) imap_get( - q_wrapper->series_map, + *q_wrapper->series_mapp, series->id); if (series != NULL) @@ -1246,12 +1251,12 @@ static void enter_series_name(uv_async_t * handle) } imap_free( - q_wrapper->series_map, + *q_wrapper->series_mapp, (imap_free_cb) &siridb__series_decref); - q_wrapper->series_map = imap_new(); + *q_wrapper->series_mapp = imap_new(); - if (q_wrapper->series_map == NULL) + if (*q_wrapper->series_mapp == NULL) { if (series != NULL) { @@ -1262,7 +1267,7 @@ static void enter_series_name(uv_async_t * handle) if (series != NULL) { - if (imap_set(q_wrapper->series_map, series->id, series) != 1) + if (imap_set(*q_wrapper->series_mapp, series->id, series) != 1) { siridb_series_decref(series); MEM_ERR_RET @@ -1271,11 +1276,11 @@ static void enter_series_name(uv_async_t * handle) } else if (q_wrapper->update_cb == &imap_symmetric_difference_ref) { - switch (imap_set(q_wrapper->series_map, series->id, series)) + switch (imap_set(*q_wrapper->series_mapp, series->id, series)) { case 0: series = (siridb_series_t *) imap_pop( - q_wrapper->series_map, + *q_wrapper->series_mapp, series->id); siridb_series_decref(series); break; @@ -1301,15 +1306,29 @@ static void enter_series_name(uv_async_t * handle) static void enter_series_match(uv_async_t * handle) { siridb_query_t * query = (siridb_query_t *) handle->data; + query_wrapper_t * q_wrapper = query->data; + siridb_sset_t * sset; - if ((((query_wrapper_t *) query->data)->series_map = imap_new()) == NULL) + if ((q_wrapper->series_vec = vec_new(1)) == NULL || + (sset = siridb_sset_new()) == NULL) { MEM_ERR_RET } + vec_append(q_wrapper->series_vec, sset); + + q_wrapper->series_mapp = &sset->series_map; + SIRIPARSER_NEXT_NODE } +static void enter_series_parenthesis(uv_async_t * handle) +{ + siridb_query_t * query = (siridb_query_t *) handle->data; + + SIRIPARSER_ASYNC_NEXT_NODE +} + static void enter_series_all(uv_async_t * handle) { siridb_query_t * query = (siridb_query_t *) handle->data; @@ -1330,12 +1349,12 @@ static void enter_series_all(uv_async_t * handle) ( q_wrapper->update_cb == NULL || q_wrapper->update_cb == &imap_union_ref || q_wrapper->update_cb == &imap_symmetric_difference_ref) ? - siridb->series_map : q_wrapper->series_map); + siridb->series_map : *q_wrapper->series_mapp); uv_mutex_unlock(&siridb->series_mutex); q_wrapper->series_tmp = (q_wrapper->update_cb == NULL) ? - q_wrapper->series_map : imap_new(); + *q_wrapper->series_mapp : imap_new(); if (q_wrapper->vec == NULL || q_wrapper->series_tmp == NULL) { @@ -1360,7 +1379,7 @@ static void enter_series_all(uv_async_t * handle) if (q_wrapper->update_cb != NULL) { (*q_wrapper->update_cb)( - q_wrapper->series_map, + *q_wrapper->series_mapp, q_wrapper->series_tmp, (imap_free_cb) &siridb__series_decref); } @@ -1401,12 +1420,12 @@ static void enter_series_re(uv_async_t * handle) ( q_wrapper->update_cb == NULL || q_wrapper->update_cb == &imap_union_ref || q_wrapper->update_cb == &imap_symmetric_difference_ref) ? - siridb->series_map : q_wrapper->series_map); + siridb->series_map : *q_wrapper->series_mapp); uv_mutex_unlock(&siridb->series_mutex); q_wrapper->series_tmp = (q_wrapper->update_cb == NULL) ? - q_wrapper->series_map : imap_new(); + *q_wrapper->series_mapp : imap_new(); if (q_wrapper->vec == NULL || q_wrapper->series_tmp == NULL) { @@ -1435,7 +1454,7 @@ static void enter_series_re(uv_async_t * handle) /* handle is handled or a signal is raised */ } -static void enter_series_sep(uv_async_t * handle) +static void enter_series_setopr(uv_async_t * handle) { siridb_query_t * query = (siridb_query_t *) handle->data; query_wrapper_t * q_wrapper = (query_wrapper_t *) query->data; @@ -1762,8 +1781,8 @@ static void exit_count_series(uv_async_t * handle) if (q_count->where_expr == NULL) { - q_count->n = (q_count->series_map == NULL) ? - siridb->series_map->len : q_count->series_map->len; + q_count->n = (q_count->series_mapp == NULL) ? + siridb->series_map->len : (*q_count->series_mapp)->len; if (IS_MASTER) { @@ -1785,8 +1804,8 @@ static void exit_count_series(uv_async_t * handle) uv_mutex_lock(&siridb->series_mutex); q_count->vec = imap_2vec_ref( - (q_count->series_map == NULL) ? - siridb->series_map : q_count->series_map); + (q_count->series_mapp == NULL) ? + siridb->series_map : *q_count->series_mapp); uv_mutex_unlock(&siridb->series_mutex); @@ -1832,8 +1851,8 @@ static void exit_count_series_length(uv_async_t * handle) uv_mutex_lock(&siridb->series_mutex); - vec = imap_2vec((q_count->series_map == NULL) ? - siridb->series_map : q_count->series_map); + vec = imap_2vec((q_count->series_mapp == NULL) ? + siridb->series_map : *q_count->series_mapp); uv_mutex_unlock(&siridb->series_mutex); @@ -1872,8 +1891,8 @@ static void exit_count_series_length(uv_async_t * handle) uv_mutex_lock(&siridb->series_mutex); q_count->vec = imap_2vec_ref( - (q_count->series_map == NULL) ? - siridb->series_map : q_count->series_map); + (q_count->series_mapp == NULL) ? + siridb->series_map : *q_count->series_mapp); uv_mutex_unlock(&siridb->series_mutex); @@ -2363,9 +2382,11 @@ static void exit_drop_series(uv_async_t * handle) */ uv_mutex_lock(&siridb->series_mutex); - q_drop->vec = (q_drop->series_map == NULL) ? - imap_2vec_ref(siridb->series_map) : - imap_vec_pop(q_drop->series_map); + q_drop->vec = q_drop->series_tmp != NULL + ? imap_vec_pop(q_drop->series_tmp) + : q_drop->series_mapp != NULL + ? imap_vec_pop(*q_drop->series_mapp) + : imap_2vec_ref(siridb->series_map); uv_mutex_unlock(&siridb->series_mutex); @@ -2374,11 +2395,11 @@ static void exit_drop_series(uv_async_t * handle) MEM_ERR_RET } - if (q_drop->series_map != NULL) + if (q_drop->series_mapp != NULL) { /* now we can simply destroy the imap in case we had one */ - imap_free(q_drop->series_map, NULL); - q_drop->series_map = NULL; + imap_free(*q_drop->series_mapp, NULL); + *q_drop->series_mapp = NULL; } /* @@ -2389,9 +2410,11 @@ static void exit_drop_series(uv_async_t * handle) if (q_drop->where_expr != NULL) { /* create a new one */ - q_drop->series_map = imap_new(); - if (q_drop->series_map == NULL) + /* TODO: Re-write using tmp instead of map */ + q_drop->series_tmp = imap_new(); + + if (q_drop->series_tmp == NULL) { MEM_ERR_RET } @@ -2913,8 +2936,8 @@ static void exit_list_series(uv_async_t * handle) uv_mutex_lock(&siridb->series_mutex); - q_list->vec = imap_2vec_ref((q_list->series_map == NULL) ? - siridb->series_map : q_list->series_map); + q_list->vec = imap_2vec_ref((q_list->series_mapp == NULL) ? + siridb->series_map : *q_list->series_mapp); uv_mutex_unlock(&siridb->series_mutex); @@ -3290,6 +3313,13 @@ static void exit_series_match(uv_async_t * handle) SIRIPARSER_ASYNC_NEXT_NODE } +static void exit_series_parenthesis(uv_async_t * handle) +{ + siridb_query_t * query = (siridb_query_t *) handle->data; + + SIRIPARSER_ASYNC_NEXT_NODE +} + static void exit_select_aggregate(uv_async_t * handle) { siridb_query_t * query = (siridb_query_t *) handle->data; @@ -3298,7 +3328,7 @@ static void exit_select_aggregate(uv_async_t * handle) if (q_select->where_expr != NULL) { /* we transform the references from imap to vec */ - q_select->vec = imap_vec_pop(q_select->series_map); + q_select->vec = imap_vec_pop(*q_select->series_mapp); if (q_select->vec == NULL) { @@ -3306,12 +3336,13 @@ static void exit_select_aggregate(uv_async_t * handle) } /* now we can simply destroy the imap */ - imap_free(q_select->series_map, NULL); + imap_free(*q_select->series_mapp, NULL); + *q_select->series_mapp = NULL; /* create a new one */ - q_select->series_map = imap_new(); + q_select->series_tmp = imap_new(); - if (q_select->series_map == NULL) + if (q_select->series_tmp == NULL) { MEM_ERR_RET } @@ -4555,7 +4586,7 @@ static void async_filter_series(uv_async_t * handle) (cexpr_cb_t) siridb_series_cexpr_cb, series)) { - if (imap_add(q_wrapper->series_map, series->id, series)) + if (imap_add(q_wrapper->series_tmp, series->id, series)) { log_critical("Cannot add filtered series to internal map."); siridb_series_decref(series); @@ -5050,7 +5081,7 @@ static void async_series_re(uv_async_t * handle) if (q_wrapper->update_cb != NULL) { (*q_wrapper->update_cb)( - q_wrapper->series_map, + *q_wrapper->series_mapp, q_wrapper->series_tmp, (imap_free_cb) &siridb__series_decref); } diff --git a/src/siri/db/queries.c b/src/siri/db/queries.c index db0ae4b3..7a2ef72d 100644 --- a/src/siri/db/queries.c +++ b/src/siri/db/queries.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -14,10 +15,11 @@ #define QUERIES_NEW(q) \ q->flags = 0; \ -q->series_map = NULL; \ +q->series_mapp = NULL; \ q->series_tmp = NULL; \ -q->vec = NULL; \ -q->vec_index = 0; \ +q->series_vec = NULL; \ +q->vec = NULL; \ +q->vec_index = 0; \ q->pmap = NULL; \ q->update_cb = NULL; \ q->where_expr = NULL; \ @@ -26,27 +28,22 @@ q->match_data = NULL; #define QUERIES_FREE(q, handle) \ -if (q->series_map != NULL) \ -{ \ - imap_free( \ - q->series_map, \ - (imap_free_cb) &siridb__series_decref); \ -} \ +vec_destroy(q->series_vec, (vec_destroy_cb) siridb_sset_free); \ if (q->series_tmp != NULL) \ { \ imap_free( \ q->series_tmp, \ (imap_free_cb) &siridb__series_decref); \ } \ -if (q->vec != NULL) \ +if (q->vec != NULL) \ { \ siridb_series_t * series; \ - for (; q->vec_index < q->vec->len; q->vec_index++) \ - { \ + for (; q->vec_index < q->vec->len; q->vec_index++) \ + { \ series = (siridb_series_t *) q->vec->data[q->vec_index]; \ - siridb_series_decref(series); \ - } \ - vec_free(q->vec); \ + siridb_series_decref(series); \ + } \ + vec_free(q->vec); \ } \ if (q->where_expr != NULL) \ { \ diff --git a/src/siri/db/sset.c b/src/siri/db/sset.c new file mode 100644 index 00000000..54b154fd --- /dev/null +++ b/src/siri/db/sset.c @@ -0,0 +1,42 @@ +/* + * sset.c - Set operations on series. + */ + +#include +#include +#include +#include + +siridb_sset_t * siridb_sset_new(void) +{ + siridb_sset_t * sset = malloc(sizeof(siridb_sset_t)); + if (sset == NULL) + { + return NULL; + } + sset->series_map = imap_new(); + sset->update_cb = NULL; + + if (sset->series_map == NULL) + { + siridb_sset_free(sset); + return NULL; + } + + return sset; +} + +void siridb_sset_free(siridb_sset_t * sset) +{ + if (sset == NULL) + { + return; + } + + if (sset->series_map) + { + imap_free(sset->series_map, (imap_free_cb) &siridb__series_decref); + } + + free(sset); +} diff --git a/src/siri/grammar/grammar.c b/src/siri/grammar/grammar.c index 0f14df21..615e2489 100644 --- a/src/siri/grammar/grammar.c +++ b/src/siri/grammar/grammar.c @@ -5,7 +5,7 @@ * should be used with the libcleri module. * * Source class: SiriGrammar - * Created at: 2018-10-29 10:52:57 + * Created at: 2019-01-02 15:54:36 */ #include "siri/grammar/grammar.h" @@ -745,8 +745,8 @@ cleri_grammar_t * compile_siri_grammar_grammar(void) ) ) ); - cleri_t * series_sep = cleri_choice( - CLERI_GID_SERIES_SEP, + cleri_t * series_setopr = cleri_choice( + CLERI_GID_SERIES_SETOPR, CLERI_FIRST_MATCH, 4, k_union, @@ -754,6 +754,13 @@ cleri_grammar_t * compile_siri_grammar_grammar(void) k_intersection, k_symmetric_difference ); + cleri_t * series_parenthesis = cleri_sequence( + CLERI_GID_SERIES_PARENTHESIS, + 3, + cleri_token(CLERI_NONE, "("), + CLERI_THIS, + cleri_token(CLERI_NONE, ")") + ); cleri_t * series_all = cleri_choice( CLERI_GID_SERIES_ALL, CLERI_FIRST_MATCH, @@ -772,15 +779,27 @@ cleri_grammar_t * compile_siri_grammar_grammar(void) string ); cleri_t * group_match = cleri_dup(CLERI_GID_GROUP_MATCH, r_grave_str); - cleri_t * series_match = cleri_list(CLERI_GID_SERIES_MATCH, cleri_choice( - CLERI_NONE, - CLERI_FIRST_MATCH, - 4, - series_all, - series_name, - group_match, - series_re - ), series_sep, 1, 0, 0); + cleri_t * series_match = cleri_prio( + CLERI_GID_SERIES_MATCH, + 3, + cleri_choice( + CLERI_NONE, + CLERI_FIRST_MATCH, + 4, + series_all, + series_name, + group_match, + series_re + ), + cleri_sequence( + CLERI_NONE, + 3, + CLERI_THIS, + series_setopr, + CLERI_THIS + ), + series_parenthesis + ); cleri_t * limit_expr = cleri_sequence( CLERI_GID_LIMIT_EXPR, 2, diff --git a/src/vec/vec.c b/src/vec/vec.c index f2979e1d..c9792dbc 100644 --- a/src/vec/vec.c +++ b/src/vec/vec.c @@ -32,6 +32,19 @@ vec_t * vec_new(size_t size) return vec; } +void vec_destroy(vec_t * vec, vec_destroy_cb cb) +{ + if (vec != NULL && cb) + { + size_t i; + for (i = 0; i < vec->len; ++i) + { + cb(vec->data[i]); + } + } + free(vec); +} + /* * Returns NULL in case an error has occurred. */ -- 2.39.5