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