]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: introduce column type
authorKarel Zak <kzak@redhat.com>
Wed, 27 Sep 2023 12:00:38 +0000 (14:00 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 20 Nov 2023 21:25:46 +0000 (22:25 +0100)
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 <kzak@redhat.com>
libsmartcols/src/column.c
libsmartcols/src/filter-param.c
libsmartcols/src/libsmartcols.h.in
libsmartcols/src/libsmartcols.sym
libsmartcols/src/smartcolsP.h

index f0a395373da4d25fd865ecadef3dea394d0727f6..bf3b1a2d0dfec1c8499174bce4e8fd07319b73fb 100644 (file)
@@ -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:
index 1bcfd8988b5f826749ad37c03e239d9293d9dd7d..b05eb808e11d5fdd4b35dfc404159b50c25c5716 100644 (file)
@@ -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)
index 509fe7648a1771beb883ee3cb4d621a6bf9d68df..455c011d46abc3bca0b5785c554d123f830353cc 100644 (file)
@@ -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);
 
index 5e11ba19b33f814bafa00ded2168d9a9497ab0b0..cf025e5ce71db3846b2ef0cfe726e400454c7918 100644 (file)
@@ -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;
index fd4dc4134360a652ac496fa5ba428ce7ae3575c7..75fb7ffa37af7761b11e3713f0191203f35f0a77 100644 (file)
@@ -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 */