xref: /openbmc/qemu/qapi/string-output-visitor.c (revision c7bcc85d)
1 /*
2  * String printing Visitor
3  *
4  * Copyright Red Hat, Inc. 2012
5  *
6  * Author: Paolo Bonzini <pbonzini@redhat.com>
7  *
8  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
9  * See the COPYING.LIB file in the top-level directory.
10  *
11  */
12 
13 #include "qemu-common.h"
14 #include "qapi/string-output-visitor.h"
15 #include "qapi/visitor-impl.h"
16 #include "qapi/qmp/qerror.h"
17 #include "qemu/host-utils.h"
18 
19 struct StringOutputVisitor
20 {
21     Visitor visitor;
22     bool human;
23     char *string;
24 };
25 
26 static void string_output_set(StringOutputVisitor *sov, char *string)
27 {
28     g_free(sov->string);
29     sov->string = string;
30 }
31 
32 static void print_type_int(Visitor *v, int64_t *obj, const char *name,
33                            Error **errp)
34 {
35     StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
36     char *out;
37 
38     if (sov->human) {
39         out = g_strdup_printf("%lld (%#llx)", (long long) *obj, (long long) *obj);
40     } else {
41         out = g_strdup_printf("%lld", (long long) *obj);
42     }
43     string_output_set(sov, out);
44 }
45 
46 static void print_type_size(Visitor *v, uint64_t *obj, const char *name,
47                            Error **errp)
48 {
49     StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
50     static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T' };
51     uint64_t div, val;
52     char *out;
53     int i;
54 
55     if (!sov->human) {
56         out = g_strdup_printf("%llu", (long long) *obj);
57         string_output_set(sov, out);
58         return;
59     }
60 
61     val = *obj;
62 
63     /* Compute floor(log2(val)).  */
64     i = 64 - clz64(val);
65 
66     /* Find the power of 1024 that we'll display as the units.  */
67     i /= 10;
68     if (i >= ARRAY_SIZE(suffixes)) {
69         i = ARRAY_SIZE(suffixes) - 1;
70     }
71     div = 1ULL << (i * 10);
72 
73     out = g_strdup_printf("%0.03f%c", (double)val/div, suffixes[i]);
74     string_output_set(sov, out);
75 }
76 
77 static void print_type_bool(Visitor *v, bool *obj, const char *name,
78                             Error **errp)
79 {
80     StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
81     string_output_set(sov, g_strdup(*obj ? "true" : "false"));
82 }
83 
84 static void print_type_str(Visitor *v, char **obj, const char *name,
85                            Error **errp)
86 {
87     StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
88     char *out;
89 
90     if (sov->human) {
91         out = *obj ? g_strdup_printf("\"%s\"", *obj) : g_strdup("<null>");
92     } else {
93         out = g_strdup(*obj ? *obj : "");
94     }
95     string_output_set(sov, out);
96 }
97 
98 static void print_type_number(Visitor *v, double *obj, const char *name,
99                               Error **errp)
100 {
101     StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
102     string_output_set(sov, g_strdup_printf("%f", *obj));
103 }
104 
105 char *string_output_get_string(StringOutputVisitor *sov)
106 {
107     char *string = sov->string;
108     sov->string = NULL;
109     return string;
110 }
111 
112 Visitor *string_output_get_visitor(StringOutputVisitor *sov)
113 {
114     return &sov->visitor;
115 }
116 
117 void string_output_visitor_cleanup(StringOutputVisitor *sov)
118 {
119     g_free(sov->string);
120     g_free(sov);
121 }
122 
123 StringOutputVisitor *string_output_visitor_new(bool human)
124 {
125     StringOutputVisitor *v;
126 
127     v = g_malloc0(sizeof(*v));
128 
129     v->human = human;
130     v->visitor.type_enum = output_type_enum;
131     v->visitor.type_int = print_type_int;
132     v->visitor.type_size = print_type_size;
133     v->visitor.type_bool = print_type_bool;
134     v->visitor.type_str = print_type_str;
135     v->visitor.type_number = print_type_number;
136 
137     return v;
138 }
139