From: Karel Zak Date: Thu, 31 Aug 2023 15:41:04 +0000 (+0200) Subject: libsmartcols: add API to join filter and columns X-Git-Tag: v2.40-rc1~151^2~80 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=67fb7851e4b65ca1567f33bad7059de8d9dd3833;p=thirdparty%2Futil-linux.git libsmartcols: add API to join filter and columns Signed-off-by: Karel Zak --- diff --git a/libsmartcols/samples/filter.c b/libsmartcols/samples/filter.c index e043e46acf..aaf7fb69ea 100644 --- a/libsmartcols/samples/filter.c +++ b/libsmartcols/samples/filter.c @@ -86,7 +86,9 @@ int main(int argc, char *argv[]) { struct libscols_table *tb; struct libscols_filter *fltr = NULL; + struct libscols_iter *itr = NULL; int c, i, json = 0, dump = 0; + int rc = 0; static const struct option longopts[] = { { "json", 0, NULL, 'J' }, @@ -132,11 +134,34 @@ int main(int argc, char *argv[]) scols_table_enable_json(tb, json); setup_columns(tb); + if (fltr) { + const char *name = NULL; + + itr = scols_new_iter(SCOLS_ITER_FORWARD); + if (!itr) + err(EXIT_FAILURE, "failed to allocate iterator"); + + while (scols_filter_next_name(fltr, itr, &name) == 0) { + struct libscols_column *col = + scols_table_get_column_by_name(tb, name); + if (!col) { + warnx("unknown column '%s' in filter", name); + rc++; + continue; + } + scols_filter_assign_column(fltr, name, col); + } + if (rc) + goto done; + } + for (i = 0; i < 10; i++) add_line(tb, i + 1); scols_print_table(tb); +done: scols_unref_table(tb); scols_unref_filter(fltr); - return EXIT_SUCCESS; + scols_free_iter(itr); + return rc ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/libsmartcols/src/filter.c b/libsmartcols/src/filter.c index 30d601a686..025b672010 100644 --- a/libsmartcols/src/filter.c +++ b/libsmartcols/src/filter.c @@ -18,6 +18,7 @@ struct libscols_filter *scols_new_filter(const char *str) if (!fltr) return NULL; fltr->refcount = 1; + INIT_LIST_HEAD(&fltr->params); if (str && scols_filter_parse_string(fltr, str) != 0) { scols_unref_filter(fltr); @@ -73,7 +74,7 @@ static struct filter_node *new_node(enum filter_ntype type, size_t sz) } struct filter_node *filter_new_param( - struct libscols_filter *fltr __attribute__((__unused__)), + struct libscols_filter *fltr, enum filter_ptype type, void *data) { @@ -82,6 +83,7 @@ struct filter_node *filter_new_param( F_NODE_PARAM, sizeof(struct filter_param)); n->type = type; + INIT_LIST_HEAD(&n->pr_params); switch (type) { case F_PARAM_STRING: @@ -107,6 +109,9 @@ struct filter_node *filter_new_param( n->val.boolean = *((bool *) data) == 0 ? 0 : 1; break; } + + list_add_tail(&n->pr_params, &fltr->params); + return (struct filter_node *) n; } @@ -114,6 +119,9 @@ static void free_param(struct filter_param *n) { if (n->type == F_PARAM_NAME || n->type == F_PARAM_STRING) free(n->val.str); + + list_del_init(&n->pr_params); + scols_unref_column(n->col); free(n); } @@ -260,6 +268,8 @@ static void filter_dump_node(struct ul_jsonwrt *json, struct filter_node *n) } } + + extern int yyparse(void *scanner, struct libscols_filter *fltr); int scols_filter_parse_string(struct libscols_filter *fltr, const char *str) @@ -304,3 +314,58 @@ const char *scols_filter_get_errmsg(struct libscols_filter *fltr) { return fltr ? fltr->errmsg : NULL; } + +static int filter_next_param(struct libscols_filter *fltr, + struct libscols_iter *itr, struct filter_param **prm) +{ + int rc = 1; + + if (!fltr || !itr || !prm) + return -EINVAL; + *prm = NULL; + + if (!itr->head) + SCOLS_ITER_INIT(itr, &fltr->params); + if (itr->p != itr->head) { + SCOLS_ITER_ITERATE(itr, *prm, struct filter_param, pr_params); + rc = 0; + } + + return rc; +} + +int scols_filter_next_name(struct libscols_filter *fltr, + struct libscols_iter *itr, const char **name) +{ + struct filter_param *prm = NULL; + int rc = 0; + + *name = NULL; + + do { + rc = filter_next_param(fltr, itr, &prm); + if (rc == 0 && prm->type == F_PARAM_NAME) + *name = prm->val.str; + } while (rc == 0 && !*name); + + return rc; +} + +int scols_filter_assign_column(struct libscols_filter *fltr, + const char *name, struct libscols_column *col) +{ + struct libscols_iter itr; + struct filter_param *prm = NULL; + int ct = 0; + + scols_reset_iter(&itr, SCOLS_ITER_FORWARD); + while (filter_next_param(fltr, &itr, &prm) == 0) { + if (prm->type != F_PARAM_NAME || strcmp(name, prm->val.str) != 0) + continue; + prm->col = col; + scols_ref_column(col); + ct++; + } + + return ct == 0 ? 1 : 0; +} diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index 2262cb149c..bb23e1f08b 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -374,6 +374,11 @@ extern void scols_unref_filter(struct libscols_filter *fltr); extern int scols_dump_filter(struct libscols_filter *fltr, FILE *out); extern const char *scols_filter_get_errmsg(struct libscols_filter *fltr); +extern int scols_filter_next_name(struct libscols_filter *fltr, + struct libscols_iter *itr, const char **name); +extern int scols_filter_assign_column(struct libscols_filter *fltr, + const char *name, struct libscols_column *col); + #ifdef __cplusplus } #endif diff --git a/libsmartcols/src/libsmartcols.sym b/libsmartcols/src/libsmartcols.sym index 4fb97f43e7..b50c80d79b 100644 --- a/libsmartcols/src/libsmartcols.sym +++ b/libsmartcols/src/libsmartcols.sym @@ -226,4 +226,6 @@ SMARTCOLS_2.40 { scols_new_filter; scols_unref_filter; scols_filter_get_errmsg; + scols_filter_next_name; + scols_filter_assign_column; } SMARTCOLS_2.39; diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index 86c07ea40e..15d6fc62d1 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -532,6 +532,9 @@ struct filter_param { long double fnum; bool boolean; } val; + + struct list_head pr_params; + struct libscols_column *col; }; struct filter_expr { @@ -547,6 +550,8 @@ struct libscols_filter { char *errmsg; struct filter_node *root; FILE *src; + + struct list_head params; }; /* required by parser */