]> git.proxmox.com Git - mirror_qemu.git/blobdiff - qapi/string-output-visitor.c
Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging
[mirror_qemu.git] / qapi / string-output-visitor.c
index 7ab64468d9a58a6a4529dba6a08435a17d07af36..5115536b153903dc1abae78ca70d76a1f69e1194 100644 (file)
  */
 
 #include "qemu/osdep.h"
-#include "qemu-common.h"
+#include "qemu/cutils.h"
 #include "qapi/string-output-visitor.h"
 #include "qapi/visitor-impl.h"
-#include "qemu/host-utils.h"
 #include <math.h>
 #include "qemu/range.h"
 
@@ -66,6 +65,7 @@ struct StringOutputVisitor
     } range_start, range_end;
     GList *ranges;
     void *list; /* Only needed for sanity checking the caller */
+    unsigned int struct_nesting;
 };
 
 static StringOutputVisitor *to_sov(Visitor *v)
@@ -75,11 +75,27 @@ static StringOutputVisitor *to_sov(Visitor *v)
 
 static void string_output_set(StringOutputVisitor *sov, char *string)
 {
-    if (sov->string) {
-        g_string_free(sov->string, true);
+    switch (sov->list_mode) {
+    case LM_STARTED:
+        sov->list_mode = LM_IN_PROGRESS;
+        /* fall through */
+    case LM_NONE:
+        if (sov->string) {
+            g_string_free(sov->string, true);
+        }
+        sov->string = g_string_new(string);
+        g_free(string);
+        break;
+
+    case LM_IN_PROGRESS:
+    case LM_END:
+        g_string_append(sov->string, ", ");
+        g_string_append(sov->string, string);
+        break;
+
+    default:
+        abort();
     }
-    sov->string = g_string_new(string);
-    g_free(string);
 }
 
 static void string_output_append(StringOutputVisitor *sov, int64_t a)
@@ -123,12 +139,16 @@ static void format_string(StringOutputVisitor *sov, Range *r, bool next,
     }
 }
 
-static void print_type_int64(Visitor *v, const char *name, int64_t *obj,
+static bool print_type_int64(Visitor *v, const char *name, int64_t *obj,
                              Error **errp)
 {
     StringOutputVisitor *sov = to_sov(v);
     GList *l;
 
+    if (sov->struct_nesting) {
+        return true;
+    }
+
     switch (sov->list_mode) {
     case LM_NONE:
         string_output_append(sov, *obj);
@@ -138,7 +158,7 @@ static void print_type_int64(Visitor *v, const char *name, int64_t *obj,
         sov->range_start.s = *obj;
         sov->range_end.s = *obj;
         sov->list_mode = LM_IN_PROGRESS;
-        return;
+        return true;
 
     case LM_IN_PROGRESS:
         if (sov->range_end.s + 1 == *obj) {
@@ -155,7 +175,7 @@ static void print_type_int64(Visitor *v, const char *name, int64_t *obj,
             sov->range_start.s = *obj;
             sov->range_end.s = *obj;
         }
-        return;
+        return true;
 
     case LM_END:
         if (sov->range_end.s + 1 == *obj) {
@@ -197,27 +217,33 @@ static void print_type_int64(Visitor *v, const char *name, int64_t *obj,
         }
         g_string_append(sov->string, ")");
     }
+
+    return true;
 }
 
-static void print_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+static bool print_type_uint64(Visitor *v, const char *name, uint64_t *obj,
                              Error **errp)
 {
     /* FIXME: print_type_int64 mishandles values over INT64_MAX */
     int64_t i = *obj;
-    print_type_int64(v, name, &i, errp);
+    return print_type_int64(v, name, &i, errp);
 }
 
-static void print_type_size(Visitor *v, const char *name, uint64_t *obj,
+static bool print_type_size(Visitor *v, const char *name, uint64_t *obj,
                             Error **errp)
 {
     StringOutputVisitor *sov = to_sov(v);
     uint64_t val;
     char *out, *psize;
 
+    if (sov->struct_nesting) {
+        return true;
+    }
+
     if (!sov->human) {
         out = g_strdup_printf("%"PRIu64, *obj);
         string_output_set(sov, out);
-        return;
+        return true;
     }
 
     val = *obj;
@@ -226,56 +252,104 @@ static void print_type_size(Visitor *v, const char *name, uint64_t *obj,
     string_output_set(sov, out);
 
     g_free(psize);
+    return true;
 }
 
-static void print_type_bool(Visitor *v, const char *name, bool *obj,
+static bool print_type_bool(Visitor *v, const char *name, bool *obj,
                             Error **errp)
 {
     StringOutputVisitor *sov = to_sov(v);
+
+    if (sov->struct_nesting) {
+        return true;
+    }
+
     string_output_set(sov, g_strdup(*obj ? "true" : "false"));
+    return true;
 }
 
-static void print_type_str(Visitor *v, const char *name, char **obj,
+static bool print_type_str(Visitor *v, const char *name, char **obj,
                            Error **errp)
 {
     StringOutputVisitor *sov = to_sov(v);
     char *out;
 
+    if (sov->struct_nesting) {
+        return true;
+    }
+
     if (sov->human) {
         out = *obj ? g_strdup_printf("\"%s\"", *obj) : g_strdup("<null>");
     } else {
         out = g_strdup(*obj ? *obj : "");
     }
     string_output_set(sov, out);
+    return true;
 }
 
-static void print_type_number(Visitor *v, const char *name, double *obj,
+static bool print_type_number(Visitor *v, const char *name, double *obj,
                               Error **errp)
 {
     StringOutputVisitor *sov = to_sov(v);
-    string_output_set(sov, g_strdup_printf("%f", *obj));
+
+    if (sov->struct_nesting) {
+        return true;
+    }
+
+    string_output_set(sov, g_strdup_printf("%.17g", *obj));
+    return true;
 }
 
-static void print_type_null(Visitor *v, const char *name, QNull **obj,
+static bool print_type_null(Visitor *v, const char *name, QNull **obj,
                             Error **errp)
 {
     StringOutputVisitor *sov = to_sov(v);
     char *out;
 
+    if (sov->struct_nesting) {
+        return true;
+    }
+
     if (sov->human) {
         out = g_strdup("<null>");
     } else {
         out = g_strdup("");
     }
     string_output_set(sov, out);
+    return true;
+}
+
+static bool start_struct(Visitor *v, const char *name, void **obj,
+                         size_t size, Error **errp)
+{
+    StringOutputVisitor *sov = to_sov(v);
+
+    sov->struct_nesting++;
+    return true;
+}
+
+static void end_struct(Visitor *v, void **obj)
+{
+    StringOutputVisitor *sov = to_sov(v);
+
+    if (--sov->struct_nesting) {
+        return;
+    }
+
+    /* TODO actually print struct fields */
+    string_output_set(sov, g_strdup("<omitted>"));
 }
 
-static void
+static bool
 start_list(Visitor *v, const char *name, GenericList **list, size_t size,
            Error **errp)
 {
     StringOutputVisitor *sov = to_sov(v);
 
+    if (sov->struct_nesting) {
+        return true;
+    }
+
     /* we can't traverse a list in a list */
     assert(sov->list_mode == LM_NONE);
     /* We don't support visits without a list */
@@ -285,6 +359,7 @@ start_list(Visitor *v, const char *name, GenericList **list, size_t size,
     if (*list && (*list)->next) {
         sov->list_mode = LM_STARTED;
     }
+    return true;
 }
 
 static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
@@ -292,6 +367,10 @@ static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
     StringOutputVisitor *sov = to_sov(v);
     GenericList *ret = tail->next;
 
+    if (sov->struct_nesting) {
+        return ret;
+    }
+
     if (ret && !ret->next) {
         sov->list_mode = LM_END;
     }
@@ -302,6 +381,10 @@ static void end_list(Visitor *v, void **obj)
 {
     StringOutputVisitor *sov = to_sov(v);
 
+    if (sov->struct_nesting) {
+        return;
+    }
+
     assert(sov->list == obj);
     assert(sov->list_mode == LM_STARTED ||
            sov->list_mode == LM_END ||
@@ -356,6 +439,8 @@ Visitor *string_output_visitor_new(bool human, char **result)
     v->visitor.type_str = print_type_str;
     v->visitor.type_number = print_type_number;
     v->visitor.type_null = print_type_null;
+    v->visitor.start_struct = start_struct;
+    v->visitor.end_struct = end_struct;
     v->visitor.start_list = start_list;
     v->visitor.next_list = next_list;
     v->visitor.end_list = end_list;