]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
format-table: add a new JSON cell type
authorLennart Poettering <lennart@amutable.com>
Wed, 18 Feb 2026 12:45:52 +0000 (13:45 +0100)
committerLennart Poettering <lennart@amutable.com>
Fri, 20 Feb 2026 07:15:29 +0000 (08:15 +0100)
This formats the specified json variant as a string, and displays it in
a cell.

src/shared/format-table.c
src/shared/format-table.h

index 9f6c46afb75d3602674ccbacf09cf0a03257f690..8b5b88370f13cedf3bf7b8bca17151b272a5bcb6 100644 (file)
@@ -14,6 +14,7 @@
 #include "glyph-util.h"
 #include "gunicode.h"
 #include "in-addr-util.h"
+#include "json-util.h"
 #include "memory-util.h"
 #include "memstream-util.h"
 #include "pager.h"
@@ -110,6 +111,7 @@ typedef struct TableData {
                 pid_t pid;
                 mode_t mode;
                 dev_t devnum;
+                sd_json_variant *json;
                 /* … add more here as we start supporting more cell data types … */
         };
 } TableData;
@@ -249,6 +251,9 @@ static TableData *table_data_free(TableData *d) {
         if (IN_SET(d->type, TABLE_STRV, TABLE_STRV_WRAPPED))
                 strv_free(d->strv);
 
+        if (d->type == TABLE_JSON)
+                sd_json_variant_unref(d->json);
+
         return mfree(d);
 }
 
@@ -363,6 +368,9 @@ static size_t table_data_size(TableDataType type, const void *data) {
         case TABLE_DEVNUM:
                 return sizeof(dev_t);
 
+        case TABLE_JSON:
+                return sizeof(sd_json_variant*);
+
         default:
                 assert_not_reached();
         }
@@ -445,12 +453,22 @@ static TableData *table_data_new(
         d->ellipsize_percent = ellipsize_percent;
         d->uppercase = uppercase;
 
-        if (IN_SET(type, TABLE_STRV, TABLE_STRV_WRAPPED)) {
+        switch (type) {
+
+        case TABLE_STRV:
+        case TABLE_STRV_WRAPPED:
                 d->strv = strv_copy(data);
                 if (!d->strv)
                         return NULL;
-        } else
+                break;
+
+        case TABLE_JSON:
+                d->json = sd_json_variant_ref((sd_json_variant*) data);
+                break;
+
+        default:
                 memcpy_safe(d->data, data, data_size);
+        }
 
         return TAKE_PTR(d);
 }
@@ -1096,6 +1114,10 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
                         data = &buffer.devnum;
                         break;
 
+                case TABLE_JSON:
+                        data = va_arg(ap, sd_json_variant*);
+                        break;
+
                 case TABLE_SET_MINIMUM_WIDTH: {
                         size_t w = va_arg(ap, size_t);
 
@@ -1506,6 +1528,9 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
 
                         return CMP(minor(a->devnum), minor(b->devnum));
 
+                case TABLE_JSON:
+                        return json_variant_compare(a->json, b->json);
+
                 default:
                         ;
                 }
@@ -2071,6 +2096,18 @@ static const char *table_data_format(
 
                 break;
 
+        case TABLE_JSON: {
+                if (!d->json)
+                        return table_ersatz_string(t);
+
+                char *p;
+                if (sd_json_variant_format(d->json, /* flags= */ 0, &p) < 0)
+                        return NULL;
+
+                d->formatted = p;
+                break;
+        }
+
         default:
                 assert_not_reached();
         }
@@ -2284,6 +2321,9 @@ static bool table_data_isempty(const TableData *d) {
         if (IN_SET(d->type, TABLE_STRV, TABLE_STRV_WRAPPED))
                 return strv_isempty(d->strv);
 
+        if (d->type == TABLE_JSON)
+                return sd_json_variant_is_null(d->json);
+
         /* Note that an empty string we do not consider empty here! */
         return false;
 }
@@ -2991,6 +3031,15 @@ static int table_data_to_json(TableData *d, sd_json_variant **ret) {
                                                   SD_JSON_BUILD_UNSIGNED(major(d->devnum)),
                                                   SD_JSON_BUILD_UNSIGNED(minor(d->devnum))));
 
+        case TABLE_JSON:
+                if (!d->json)
+                        return sd_json_variant_new_null(ret);
+
+                if (ret)
+                        *ret = sd_json_variant_ref(d->json);
+
+                return 0;
+
         case TABLE_STRING_WITH_ANSI: {
                 _cleanup_free_ char *s = strdup(d->string);
                 if (!s)
index a6a06a009ab7ee3f0be159bd60364832b2d27aad..ec9989c54c88a8cefb0217452fd54769e957aae3 100644 (file)
@@ -58,6 +58,7 @@ typedef enum TableDataType {
         TABLE_MODE,            /* as in UNIX file mode (mode_t), in typical octal output */
         TABLE_MODE_INODE_TYPE, /* also mode_t, but displays only the inode type as string */
         TABLE_DEVNUM,          /* a dev_t, displayed in the usual major:minor way */
+        TABLE_JSON,            /* an sd_json_variant, for output formatted into text */
         _TABLE_DATA_TYPE_MAX,
 
         /* The following are not really data types, but commands for table_add_cell_many() to make changes to