From: Karel Zak Date: Wed, 27 Sep 2023 12:00:38 +0000 (+0200) Subject: libsmartcols: introduce column type X-Git-Tag: v2.40-rc1~151^2~47 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=98c12238b3194cadd6eb0df5704f32903f611cdc;p=thirdparty%2Futil-linux.git libsmartcols: introduce column type Now the column can define JSON-type, this commit introduces data-type. This type is hint for filters and counters how to convert strings from cells to raw data. If the conversion from string is not possible, then application can define callback for this purpose (aka. "datafunc"), this function has to return the raw data as a void pointer. This solution allows to use human readable things in cells (e.g. "123MiB"), but filters and counters can still use the original data. Signed-off-by: Karel Zak --- diff --git a/libsmartcols/src/column.c b/libsmartcols/src/column.c index f0a395373d..bf3b1a2d0d 100644 --- a/libsmartcols/src/column.c +++ b/libsmartcols/src/column.c @@ -210,6 +210,42 @@ int scols_column_get_json_type(const struct libscols_column *cl) } +/** + * scols_column_set_data_type: + * @cl: a pointer to a struct libscols_column instance + * @type: SCOLS_DATA_* + * + * The table always keep data in strings in form that is printed on output, but + * for some internal operations (like filters or counters) it needs to convert + * the strings to usable data format. This data format is possible to specify, + * by this function. If the format is not specified then filter and counters + * try to use SCOLS_JSON_* types, if also not define than defaults to string. + * + * If simple string conversion is not possible then application (which want to + * use filters and counters) needs to define data function. See + * scols_column_set_datafunc(). + * + * Returns: 0, a negative value in case of an error. + * + * Since: 2.40 + */ +int scols_column_set_data_type(struct libscols_column *cl, int type) +{ + return cl->data_type = type; +} + +/** + * scols_column_get_data_type: + * @cl: a pointer to a struct libscols_column instance + * + * Returns: The current datatype setting of the column @cl. + * + * Since: 2.40 + */ +int scols_column_get_data_type(const struct libscols_column *cl) +{ + return cl->data_type;; +} /** * scols_column_get_table: * @cl: a pointer to a struct libscols_column instance @@ -394,6 +430,7 @@ const char *scols_column_get_color(const struct libscols_column *cl) return cl->color; } + /** * scols_wrapnl_nextchunk: * @cl: a pointer to a struct libscols_column instance @@ -591,6 +628,46 @@ int scols_column_get_wrap_data(const struct libscols_column *cl, return 0; } +/* scols_column_set_datafunc: + * @cl: a pointer to a struct libscols_column instance + * @datafunc: function to return data + * @userdata: optional stuff for callbacks + * + * The internal library operations (like filters) use standard cell data by default. + * This callback allows to use the data in another format for internal library purpose. + * + * The callback needs to return the data as pointer to void, and the datatype + * is defined by scols_column_set_data_type(). + * + * Returns: 0, a negative value in case of an error. + * + * Since: 2.40 + */ +int scols_column_set_datafunc(struct libscols_column *cl, + void *(*datafunc)(const struct libscols_column *, + struct libscols_cell *, + void *), + void *userdata) +{ + if (!cl) + return -EINVAL; + + cl->datafunc = datafunc; + cl->datafunc_data = userdata; + return 0; +} + +/** + * @cl: a pointer to a struct libscols_column instance + * + * Returns: 1 if datafunc defined, or 0 + * + * Since: 2.40 + */ +int scols_column_has_datafunc(struct libscols_column *cl) +{ + return cl && cl->datafunc != NULL ? 1 : 0; +} /** * scols_column_set_safechars: diff --git a/libsmartcols/src/filter-param.c b/libsmartcols/src/filter-param.c index 1bcfd8988b..b05eb808e1 100644 --- a/libsmartcols/src/filter-param.c +++ b/libsmartcols/src/filter-param.c @@ -223,20 +223,26 @@ int filter_param_reset_holder(struct filter_param *n) if (n->type != SCOLS_DATA_NONE) return 0; /* already set */ - switch (n->col->json_type) { - case SCOLS_JSON_NUMBER: - n->type = SCOLS_DATA_U64; - break; - case SCOLS_JSON_BOOLEAN: - n->type = SCOLS_DATA_BOOLEAN; - break; - case SCOLS_JSON_FLOAT: - n->type = SCOLS_DATA_FLOAT; - break; - case SCOLS_JSON_STRING: - default: - n->type = SCOLS_DATA_STRING; - break; + if (n->col->data_type) + /* use by application defined type */ + n->type = n->col->data_type; + else { + /* use by JSON defined type, default to string if not specified */ + switch (n->col->json_type) { + case SCOLS_JSON_NUMBER: + n->type = SCOLS_DATA_U64; + break; + case SCOLS_JSON_BOOLEAN: + n->type = SCOLS_DATA_BOOLEAN; + break; + case SCOLS_JSON_FLOAT: + n->type = SCOLS_DATA_FLOAT; + break; + case SCOLS_JSON_STRING: + default: + n->type = SCOLS_DATA_STRING; + break; + } } DBG(FPARAM, ul_debugobj(n, "holder %s type: %s", n->holder_name, datatype2str(n->type))); @@ -247,26 +253,37 @@ static int fetch_holder_data(struct libscols_filter *fltr __attribute__((__unuse struct filter_param *n, struct libscols_line *ln) { const char *data; + struct libscols_column *cl = n->col; int type = n->type; int rc = 0; if (n->has_value || n->holder != F_HOLDER_COLUMN) return 0; - if (!n->col) { + if (!cl) { DBG(FPARAM, ul_debugobj(n, "no column for %s holder", n->holder_name)); return -EINVAL; } DBG(FPARAM, ul_debugobj(n, "fetching %s data", n->holder_name)); - if (fltr->filler_cb && !scols_line_is_filled(ln, n->col->seqnum)) { - rc = fltr->filler_cb(fltr, ln, n->col->seqnum, fltr->filler_data); + if (fltr->filler_cb && !scols_line_is_filled(ln, cl->seqnum)) { + rc = fltr->filler_cb(fltr, ln, cl->seqnum, fltr->filler_data); if (rc) return rc; } - /* read column data, use it as string */ - data = scols_line_get_column_data(ln, n->col); - rc = param_set_data(n, SCOLS_DATA_STRING, data); + if (cl->datafunc) { + struct libscols_cell *ce = scols_line_get_column_cell(ln, cl); + void *data = NULL; + + if (ce) + data = cl->datafunc(n->col, ce, cl->datafunc_data); + if (data) + rc = param_set_data(n, cl->data_type, data); + } else { + /* read column data, use it as string */ + data = scols_line_get_column_data(ln, n->col); + rc = param_set_data(n, SCOLS_DATA_STRING, data); + } /* cast to the wanted type */ if (rc == 0 && type != SCOLS_DATA_NONE) diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index 509fe7648a..455c011d46 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -217,6 +217,9 @@ extern const char *scols_column_get_safechars(const struct libscols_column *cl); extern int scols_column_set_json_type(struct libscols_column *cl, int type); extern int scols_column_get_json_type(const struct libscols_column *cl); +extern int scols_column_set_data_type(struct libscols_column *cl, int type); +extern int scols_column_get_data_type(const struct libscols_column *cl); + extern int scols_column_set_flags(struct libscols_column *cl, int flags); extern int scols_column_get_flags(const struct libscols_column *cl); extern struct libscols_column *scols_new_column(void); @@ -249,6 +252,13 @@ extern int scols_column_set_wrapfunc(struct libscols_column *cl, char *, void *), void *userdata); +extern int scols_column_set_datafunc(struct libscols_column *cl, + void *(*datafunc)(const struct libscols_column *, + struct libscols_cell *, + void *), + void *userdata); +extern int scols_column_has_datafunc(struct libscols_column *cl); + extern char *scols_wrapnl_nextchunk(const struct libscols_column *cl, char *data, void *userdata); extern size_t scols_wrapnl_chunksize(const struct libscols_column *cl, const char *data, void *userdata); diff --git a/libsmartcols/src/libsmartcols.sym b/libsmartcols/src/libsmartcols.sym index 5e11ba19b3..cf025e5ce7 100644 --- a/libsmartcols/src/libsmartcols.sym +++ b/libsmartcols/src/libsmartcols.sym @@ -239,4 +239,8 @@ SMARTCOLS_2.40 { scols_counter_get_name; scols_filter_next_counter; scols_shellvar_name; + scols_column_set_datafunc; + scols_column_has_datafunc; + scols_column_set_data_type; + scols_column_get_data_type; } SMARTCOLS_2.39; diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index fd4dc41343..75fb7ffa37 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -119,6 +119,7 @@ struct libscols_column { struct libscols_wstat wstat; /* private __scols_calculate() data */ int json_type; /* SCOLS_JSON_* */ + int data_type; /* SCOLS_DATA_* */ int flags; char *color; /* default column color */ @@ -140,6 +141,11 @@ struct libscols_column { char *wrap_next; struct libscols_cell *wrap_cell; + void *(*datafunc)(const struct libscols_column *, + struct libscols_cell *, + void *); + void *datafunc_data; + struct libscols_cell header; /* column name with color etc. */ char *shellvar; /* raw colum name in shell compatible format */