This patch adds a 'SIZE' type property to those available to qdevs. It is the analogue of the OPT_SIZE property for options.
Signed-off-by: Ian Molton <ian.mol...@collabora.co.uk> --- hw/qdev-properties.c | 34 ++++++++++++++++++++++++++++++++++ hw/qdev.h | 4 ++++ parse_common.h | 40 ++++++++++++++++++++++++++++++++++++++++ qemu-option.c | 23 +++-------------------- 4 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 parse_common.h diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index bda6699..42f0d5c 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1,6 +1,7 @@ #include "sysemu.h" #include "net.h" #include "qdev.h" +#include "parse_common.h" void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) { @@ -194,6 +195,39 @@ PropertyInfo qdev_prop_hex64 = { .print = print_hex64, }; +/* --- 64bit unsigned int 'size' type --- */ + +static int parse_size(DeviceState *dev, Property *prop, const char *str) +{ + uint64_t *ptr = qdev_get_prop_ptr(dev, prop); + + if(str != NULL) + return parse_common_size(str, ptr); + + return -1; +} + +static int print_size(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + uint64_t *ptr = qdev_get_prop_ptr(dev, prop); + char suffixes[] = {'T', 'G', 'M', 'K', 'B'}; + int i; + uint64_t div; + + for(div = (long int)1 << 40 ; + !(*ptr / div) ; div >>= 10, i++); + + return snprintf(dest, len, "%0.03f%c", (double)*ptr/div, suffixes[i]); +} + +PropertyInfo qdev_prop_size = { + .name = "size", + .type = PROP_TYPE_SIZE, + .size = sizeof(uint64_t), + .parse = parse_size, + .print = print_size, +}; + /* --- string --- */ static int parse_string(DeviceState *dev, Property *prop, const char *str) diff --git a/hw/qdev.h b/hw/qdev.h index 41642ee..5521093 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -74,6 +74,7 @@ enum PropertyType { PROP_TYPE_UINT32, PROP_TYPE_INT32, PROP_TYPE_UINT64, + PROP_TYPE_SIZE, PROP_TYPE_TADDR, PROP_TYPE_MACADDR, PROP_TYPE_DRIVE, @@ -189,6 +190,7 @@ extern PropertyInfo qdev_prop_int32; extern PropertyInfo qdev_prop_uint64; extern PropertyInfo qdev_prop_hex32; extern PropertyInfo qdev_prop_hex64; +extern PropertyInfo qdev_prop_size; extern PropertyInfo qdev_prop_string; extern PropertyInfo qdev_prop_chr; extern PropertyInfo qdev_prop_ptr; @@ -226,6 +228,8 @@ extern PropertyInfo qdev_prop_pci_devfn; DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t) #define DEFINE_PROP_HEX64(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t) +#define DEFINE_PROP_SIZE(_n, _s, _f, _d) \ + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_size, uint64_t) #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, uint32_t) diff --git a/parse_common.h b/parse_common.h new file mode 100644 index 0000000..93b1fc2 --- /dev/null +++ b/parse_common.h @@ -0,0 +1,40 @@ +/* + * Common parsing routines + * + * Copyright Collabora 2009 + * + * Author: + * Ian Molton <ian.mol...@collabora.co.uk> + * + * Derived from the parser in qemu-option.c + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +static inline int parse_common_size(const char *value, uint64_t *ptr) { + char *postfix; + double sizef; + + sizef = strtod(value, &postfix); + switch (*postfix) { + case 'T': + sizef *= 1024; + case 'G': + sizef *= 1024; + case 'M': + sizef *= 1024; + case 'K': + case 'k': + sizef *= 1024; + case 'B': + case 'b': + case '\0': + *ptr = (uint64_t) sizef; + return 0; + } + + return -1; +} + diff --git a/qemu-option.c b/qemu-option.c index 49efd39..efb8e5a 100644 --- a/qemu-option.c +++ b/qemu-option.c @@ -28,6 +28,7 @@ #include "qemu-common.h" #include "qemu-option.h" +#include "parse_common.h" /* * Extracts the name of an option from the parameter string (p points at the @@ -203,28 +204,10 @@ static int parse_option_number(const char *name, const char *value, uint64_t *re static int parse_option_size(const char *name, const char *value, uint64_t *ret) { - char *postfix; - double sizef; - if (value != NULL) { - sizef = strtod(value, &postfix); - switch (*postfix) { - case 'T': - sizef *= 1024; - case 'G': - sizef *= 1024; - case 'M': - sizef *= 1024; - case 'K': - case 'k': - sizef *= 1024; - case 'b': - case '\0': - *ret = (uint64_t) sizef; - break; - default: + if(parse_common_size(value, ret) == -1) { fprintf(stderr, "Option '%s' needs size as parameter\n", name); - fprintf(stderr, "You may use k, M, G or T suffixes for " + fprintf(stderr, "You may use B, K, M, G or T suffixes for bytes " "kilobytes, megabytes, gigabytes and terabytes.\n"); return -1; } -- 1.6.5