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 #include <math.h> 19 20 struct StringOutputVisitor 21 { 22 Visitor visitor; 23 bool human; 24 char *string; 25 }; 26 27 static void string_output_set(StringOutputVisitor *sov, char *string) 28 { 29 g_free(sov->string); 30 sov->string = string; 31 } 32 33 static void print_type_int(Visitor *v, int64_t *obj, const char *name, 34 Error **errp) 35 { 36 StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); 37 char *out; 38 39 if (sov->human) { 40 out = g_strdup_printf("%lld (%#llx)", (long long) *obj, (long long) *obj); 41 } else { 42 out = g_strdup_printf("%lld", (long long) *obj); 43 } 44 string_output_set(sov, out); 45 } 46 47 static void print_type_size(Visitor *v, uint64_t *obj, const char *name, 48 Error **errp) 49 { 50 StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); 51 static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E' }; 52 uint64_t div, val; 53 char *out; 54 int i; 55 56 if (!sov->human) { 57 out = g_strdup_printf("%"PRIu64, *obj); 58 string_output_set(sov, out); 59 return; 60 } 61 62 val = *obj; 63 64 /* The exponent (returned in i) minus one gives us 65 * floor(log2(val * 1024 / 1000). The correction makes us 66 * switch to the higher power when the integer part is >= 1000. 67 */ 68 frexp(val / (1000.0 / 1024.0), &i); 69 i = (i - 1) / 10; 70 assert(i < ARRAY_SIZE(suffixes)); 71 div = 1ULL << (i * 10); 72 73 out = g_strdup_printf("%"PRIu64" (%0.3g %c%s)", val, 74 (double)val/div, suffixes[i], i ? "iB" : ""); 75 string_output_set(sov, out); 76 } 77 78 static void print_type_bool(Visitor *v, bool *obj, const char *name, 79 Error **errp) 80 { 81 StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); 82 string_output_set(sov, g_strdup(*obj ? "true" : "false")); 83 } 84 85 static void print_type_str(Visitor *v, char **obj, const char *name, 86 Error **errp) 87 { 88 StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); 89 char *out; 90 91 if (sov->human) { 92 out = *obj ? g_strdup_printf("\"%s\"", *obj) : g_strdup("<null>"); 93 } else { 94 out = g_strdup(*obj ? *obj : ""); 95 } 96 string_output_set(sov, out); 97 } 98 99 static void print_type_number(Visitor *v, double *obj, const char *name, 100 Error **errp) 101 { 102 StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v); 103 string_output_set(sov, g_strdup_printf("%f", *obj)); 104 } 105 106 char *string_output_get_string(StringOutputVisitor *sov) 107 { 108 char *string = sov->string; 109 sov->string = NULL; 110 return string; 111 } 112 113 Visitor *string_output_get_visitor(StringOutputVisitor *sov) 114 { 115 return &sov->visitor; 116 } 117 118 void string_output_visitor_cleanup(StringOutputVisitor *sov) 119 { 120 g_free(sov->string); 121 g_free(sov); 122 } 123 124 StringOutputVisitor *string_output_visitor_new(bool human) 125 { 126 StringOutputVisitor *v; 127 128 v = g_malloc0(sizeof(*v)); 129 130 v->human = human; 131 v->visitor.type_enum = output_type_enum; 132 v->visitor.type_int = print_type_int; 133 v->visitor.type_size = print_type_size; 134 v->visitor.type_bool = print_type_bool; 135 v->visitor.type_str = print_type_str; 136 v->visitor.type_number = print_type_number; 137 138 return v; 139 } 140