Patchwork [5/6] add visitor for parsing hz[KMG] input string

login
register
mail settings
Submitter Eduardo Habkost
Date Dec. 4, 2012, 7:34 p.m.
Message ID <1354649683-9078-6-git-send-email-ehabkost@redhat.com>
Download mbox | patch
Permalink /patch/203732/
State New
Headers show

Comments

Eduardo Habkost - Dec. 4, 2012, 7:34 p.m.
From: Igor Mammedov <imammedo@redhat.com>

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Andreas Färber <afaerber@suse.de>
---
 qapi/qapi-visit-core.c      | 11 +++++++++++
 qapi/qapi-visit-core.h      |  2 ++
 qapi/string-input-visitor.c | 22 ++++++++++++++++++++++
 3 files changed, 35 insertions(+)
Eduardo Habkost - Dec. 4, 2012, 7:41 p.m.
On Tue, Dec 04, 2012 at 05:34:42PM -0200, Eduardo Habkost wrote:
> From: Igor Mammedov <imammedo@redhat.com>
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Acked-by: Andreas Färber <afaerber@suse.de>

Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>


> ---
>  qapi/qapi-visit-core.c      | 11 +++++++++++
>  qapi/qapi-visit-core.h      |  2 ++
>  qapi/string-input-visitor.c | 22 ++++++++++++++++++++++
>  3 files changed, 35 insertions(+)
> 
> diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
> index 7a82b63..5c8705e 100644
> --- a/qapi/qapi-visit-core.c
> +++ b/qapi/qapi-visit-core.c
> @@ -311,3 +311,14 @@ void input_type_enum(Visitor *v, int *obj, const char *strings[],
>      g_free(enum_str);
>      *obj = value;
>  }
> +
> +void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp)
> +{
> +    if (!error_is_set(errp)) {
> +        if (v->type_freq) {
> +            v->type_freq(v, obj, name, errp);
> +        } else {
> +            v->type_int(v, obj, name, errp);
> +        }
> +    }
> +}
> diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
> index 60aceda..e5e7dd7 100644
> --- a/qapi/qapi-visit-core.h
> +++ b/qapi/qapi-visit-core.h
> @@ -62,6 +62,7 @@ struct Visitor
>      void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
>      /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
>      void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
> +    void (*type_freq)(Visitor *v, int64_t *obj, const char *name, Error **errp);
>  };
>  
>  void visit_start_handle(Visitor *v, void **obj, const char *kind,
> @@ -91,5 +92,6 @@ void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
>  void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
>  void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
>  void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
> +void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp);
>  
>  #endif
> diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
> index 497eb9a..74fe395 100644
> --- a/qapi/string-input-visitor.c
> +++ b/qapi/string-input-visitor.c
> @@ -110,6 +110,27 @@ static void parse_start_optional(Visitor *v, bool *present,
>      *present = true;
>  }
>  
> +static void parse_type_freq(Visitor *v, int64_t *obj, const char *name,
> +                            Error **errp)
> +{
> +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> +    char *endp = (char *) siv->string;
> +    long long val = 0;
> +
> +    errno = 0;
> +    if (siv->string) {
> +        val = strtosz_suffix_unit(siv->string, &endp,
> +                             STRTOSZ_DEFSUFFIX_B, 1000);
> +    }
> +    if (!siv->string || val == -1 || *endp) {
> +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
> +              "a value representable as a non-negative int64");
> +        return;
> +    }
> +
> +    *obj = val;
> +}
> +
>  Visitor *string_input_get_visitor(StringInputVisitor *v)
>  {
>      return &v->visitor;
> @@ -132,6 +153,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
>      v->visitor.type_str = parse_type_str;
>      v->visitor.type_number = parse_type_number;
>      v->visitor.start_optional = parse_start_optional;
> +    v->visitor.type_freq = parse_type_freq;
>  
>      v->string = str;
>      return v;
> -- 
> 1.7.11.7
> 
>
Andreas Färber - Dec. 4, 2012, 11:43 p.m.
Am 04.12.2012 20:34, schrieb Eduardo Habkost:
> From: Igor Mammedov <imammedo@redhat.com>
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Acked-by: Andreas Färber <afaerber@suse.de>

Mike, do we need to do anything here wrt deallocation visitors?
Or can you ack?

Thanks,
Andreas

> ---
>  qapi/qapi-visit-core.c      | 11 +++++++++++
>  qapi/qapi-visit-core.h      |  2 ++
>  qapi/string-input-visitor.c | 22 ++++++++++++++++++++++
>  3 files changed, 35 insertions(+)
> 
> diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
> index 7a82b63..5c8705e 100644
> --- a/qapi/qapi-visit-core.c
> +++ b/qapi/qapi-visit-core.c
> @@ -311,3 +311,14 @@ void input_type_enum(Visitor *v, int *obj, const char *strings[],
>      g_free(enum_str);
>      *obj = value;
>  }
> +
> +void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp)
> +{
> +    if (!error_is_set(errp)) {
> +        if (v->type_freq) {
> +            v->type_freq(v, obj, name, errp);
> +        } else {
> +            v->type_int(v, obj, name, errp);
> +        }
> +    }
> +}
> diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
> index 60aceda..e5e7dd7 100644
> --- a/qapi/qapi-visit-core.h
> +++ b/qapi/qapi-visit-core.h
> @@ -62,6 +62,7 @@ struct Visitor
>      void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
>      /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
>      void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
> +    void (*type_freq)(Visitor *v, int64_t *obj, const char *name, Error **errp);
>  };
>  
>  void visit_start_handle(Visitor *v, void **obj, const char *kind,
> @@ -91,5 +92,6 @@ void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
>  void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
>  void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
>  void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
> +void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp);
>  
>  #endif
> diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
> index 497eb9a..74fe395 100644
> --- a/qapi/string-input-visitor.c
> +++ b/qapi/string-input-visitor.c
> @@ -110,6 +110,27 @@ static void parse_start_optional(Visitor *v, bool *present,
>      *present = true;
>  }
>  
> +static void parse_type_freq(Visitor *v, int64_t *obj, const char *name,
> +                            Error **errp)
> +{
> +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> +    char *endp = (char *) siv->string;
> +    long long val = 0;
> +
> +    errno = 0;
> +    if (siv->string) {
> +        val = strtosz_suffix_unit(siv->string, &endp,
> +                             STRTOSZ_DEFSUFFIX_B, 1000);
> +    }
> +    if (!siv->string || val == -1 || *endp) {
> +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
> +              "a value representable as a non-negative int64");
> +        return;
> +    }
> +
> +    *obj = val;
> +}
> +
>  Visitor *string_input_get_visitor(StringInputVisitor *v)
>  {
>      return &v->visitor;
> @@ -132,6 +153,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
>      v->visitor.type_str = parse_type_str;
>      v->visitor.type_number = parse_type_number;
>      v->visitor.start_optional = parse_start_optional;
> +    v->visitor.type_freq = parse_type_freq;
>  
>      v->string = str;
>      return v;
>
Michael Roth - Dec. 5, 2012, 5:52 p.m.
On Tue, Dec 04, 2012 at 05:34:42PM -0200, Eduardo Habkost wrote:
> From: Igor Mammedov <imammedo@redhat.com>
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Acked-by: Andreas Färber <afaerber@suse.de>
> ---
>  qapi/qapi-visit-core.c      | 11 +++++++++++
>  qapi/qapi-visit-core.h      |  2 ++
>  qapi/string-input-visitor.c | 22 ++++++++++++++++++++++
>  3 files changed, 35 insertions(+)
> 
> diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
> index 7a82b63..5c8705e 100644
> --- a/qapi/qapi-visit-core.c
> +++ b/qapi/qapi-visit-core.c
> @@ -311,3 +311,14 @@ void input_type_enum(Visitor *v, int *obj, const char *strings[],
>      g_free(enum_str);
>      *obj = value;
>  }
> +
> +void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp)
> +{
> +    if (!error_is_set(errp)) {
> +        if (v->type_freq) {
> +            v->type_freq(v, obj, name, errp);
> +        } else {
> +            v->type_int(v, obj, name, errp);
> +        }
> +    }
> +}
> diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
> index 60aceda..e5e7dd7 100644
> --- a/qapi/qapi-visit-core.h
> +++ b/qapi/qapi-visit-core.h
> @@ -62,6 +62,7 @@ struct Visitor
>      void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
>      /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
>      void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
> +    void (*type_freq)(Visitor *v, int64_t *obj, const char *name, Error **errp);
>  };
>  
>  void visit_start_handle(Visitor *v, void **obj, const char *kind,
> @@ -91,5 +92,6 @@ void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
>  void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
>  void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
>  void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
> +void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp);
>  
>  #endif
> diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
> index 497eb9a..74fe395 100644
> --- a/qapi/string-input-visitor.c
> +++ b/qapi/string-input-visitor.c
> @@ -110,6 +110,27 @@ static void parse_start_optional(Visitor *v, bool *present,
>      *present = true;
>  }
>  
> +static void parse_type_freq(Visitor *v, int64_t *obj, const char *name,
> +                            Error **errp)
> +{
> +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> +    char *endp = (char *) siv->string;
> +    long long val = 0;
> +
> +    errno = 0;

If this is for strtosz_suffix_unit(), it looks like this is already
handled internally and can be dropped. Relic from a previous version
that called strtod() directly maybe?

If that's not the case, I think it should be fixed in the called function[s]
rather than for each caller.

> +    if (siv->string) {
> +        val = strtosz_suffix_unit(siv->string, &endp,
> +                             STRTOSZ_DEFSUFFIX_B, 1000);

Specifying 1000 as the unit size will make "1M" == 1000^2 as opposed to
1024^2. Is this intentional?

> +    }
> +    if (!siv->string || val == -1 || *endp) {
> +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
> +              "a value representable as a non-negative int64");
> +        return;
> +    }
> +
> +    *obj = val;
> +}
> +
>  Visitor *string_input_get_visitor(StringInputVisitor *v)
>  {
>      return &v->visitor;
> @@ -132,6 +153,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
>      v->visitor.type_str = parse_type_str;
>      v->visitor.type_number = parse_type_number;
>      v->visitor.start_optional = parse_start_optional;
> +    v->visitor.type_freq = parse_type_freq;

This seems applicable for stuff like -m 1G and potentionally some other
properties. We can make it generic later, but if we do end up re-spinning
consider something like ->type_unit_suffixed_int(). But I'm not against
leaving as is for now since I can't think of a better name for it atm :)

Whatever we call it, based on a recent discussion here:

http://lists.gnu.org/archive/html/qemu-devel/2012-11/msg02872.html

we should have a corresponding implementation in qapi-dealloc-visitor.c.
In this case You can just do:

v->visitor.type_freq = qapi_dealloc_type_int;

There aren't any problems in the current code, we just want to avoid relying on
fallbacks for the dealloc case in general because in some situations the
underlying sizes of the C types don't match and this can cause problems down
the road for the dealloc visitor even though it's okay for other visitor
implementations.

>  
>      v->string = str;
>      return v;
> -- 
> 1.7.11.7
> 
>
Eduardo Habkost - Dec. 5, 2012, 7:21 p.m.
On Wed, Dec 05, 2012 at 11:52:29AM -0600, mdroth wrote:
> On Tue, Dec 04, 2012 at 05:34:42PM -0200, Eduardo Habkost wrote:
[...]
> > diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
> > index 497eb9a..74fe395 100644
> > --- a/qapi/string-input-visitor.c
> > +++ b/qapi/string-input-visitor.c
> > @@ -110,6 +110,27 @@ static void parse_start_optional(Visitor *v, bool *present,
> >      *present = true;
> >  }
> >  
> > +static void parse_type_freq(Visitor *v, int64_t *obj, const char *name,
> > +                            Error **errp)
> > +{
> > +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> > +    char *endp = (char *) siv->string;
> > +    long long val = 0;
> > +
> > +    errno = 0;
> 
> If this is for strtosz_suffix_unit(), it looks like this is already
> handled internally and can be dropped. Relic from a previous version
> that called strtod() directly maybe?
> 
> If that's not the case, I think it should be fixed in the called function[s]
> rather than for each caller.
> 
> > +    if (siv->string) {
> > +        val = strtosz_suffix_unit(siv->string, &endp,
> > +                             STRTOSZ_DEFSUFFIX_B, 1000);
> 
> Specifying 1000 as the unit size will make "1M" == 1000^2 as opposed to
> 1024^2. Is this intentional?

I don't know if this is a good idea for a generalx-use visitor, but this is the
current behavior of "-cpu ...,tsc_freq=1M", that we need to keep for
compatibility, somehow.

> 
> > +    }
> > +    if (!siv->string || val == -1 || *endp) {
> > +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
> > +              "a value representable as a non-negative int64");
> > +        return;
> > +    }
> > +
> > +    *obj = val;
> > +}
> > +
> >  Visitor *string_input_get_visitor(StringInputVisitor *v)
> >  {
> >      return &v->visitor;
> > @@ -132,6 +153,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
> >      v->visitor.type_str = parse_type_str;
> >      v->visitor.type_number = parse_type_number;
> >      v->visitor.start_optional = parse_start_optional;
> > +    v->visitor.type_freq = parse_type_freq;
> 
> This seems applicable for stuff like -m 1G and potentionally some other
> properties. We can make it generic later, but if we do end up re-spinning
> consider something like ->type_unit_suffixed_int(). But I'm not against
> leaving as is for now since I can't think of a better name for it atm :)

I thought the visitor was going to support things like "1GHz", but if it's just
a "suffixed int" with no unit, the name could be changed, I guess.

But we still have the 1000 vs 1024 problem. On the one hand, it would be
interesting to make make it consistent and use the same base everywhere.
On the other hand, I assume we have different command-line options using
different bases and we'll need to keep compatibility.

Must all visitor functions have the
"function(Visitor *v, obj, const char *name, Error **errp)" signature,
or can we add additional type-specific arguments? (so we could tell
the visitor if the default base should be 1000 or 1024)
Michael Roth - Dec. 5, 2012, 9 p.m.
On Wed, Dec 05, 2012 at 05:21:50PM -0200, Eduardo Habkost wrote:
> On Wed, Dec 05, 2012 at 11:52:29AM -0600, mdroth wrote:
> > On Tue, Dec 04, 2012 at 05:34:42PM -0200, Eduardo Habkost wrote:
> [...]
> > > diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
> > > index 497eb9a..74fe395 100644
> > > --- a/qapi/string-input-visitor.c
> > > +++ b/qapi/string-input-visitor.c
> > > @@ -110,6 +110,27 @@ static void parse_start_optional(Visitor *v, bool *present,
> > >      *present = true;
> > >  }
> > >  
> > > +static void parse_type_freq(Visitor *v, int64_t *obj, const char *name,
> > > +                            Error **errp)
> > > +{
> > > +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> > > +    char *endp = (char *) siv->string;
> > > +    long long val = 0;
> > > +
> > > +    errno = 0;
> > 
> > If this is for strtosz_suffix_unit(), it looks like this is already
> > handled internally and can be dropped. Relic from a previous version
> > that called strtod() directly maybe?
> > 
> > If that's not the case, I think it should be fixed in the called function[s]
> > rather than for each caller.
> > 
> > > +    if (siv->string) {
> > > +        val = strtosz_suffix_unit(siv->string, &endp,
> > > +                             STRTOSZ_DEFSUFFIX_B, 1000);
> > 
> > Specifying 1000 as the unit size will make "1M" == 1000^2 as opposed to
> > 1024^2. Is this intentional?
> 
> I don't know if this is a good idea for a generalx-use visitor, but this is the
> current behavior of "-cpu ...,tsc_freq=1M", that we need to keep for
> compatibility, somehow.
> 
> > 
> > > +    }
> > > +    if (!siv->string || val == -1 || *endp) {
> > > +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
> > > +              "a value representable as a non-negative int64");
> > > +        return;
> > > +    }
> > > +
> > > +    *obj = val;
> > > +}
> > > +
> > >  Visitor *string_input_get_visitor(StringInputVisitor *v)
> > >  {
> > >      return &v->visitor;
> > > @@ -132,6 +153,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
> > >      v->visitor.type_str = parse_type_str;
> > >      v->visitor.type_number = parse_type_number;
> > >      v->visitor.start_optional = parse_start_optional;
> > > +    v->visitor.type_freq = parse_type_freq;
> > 
> > This seems applicable for stuff like -m 1G and potentionally some other
> > properties. We can make it generic later, but if we do end up re-spinning
> > consider something like ->type_unit_suffixed_int(). But I'm not against
> > leaving as is for now since I can't think of a better name for it atm :)
> 
> I thought the visitor was going to support things like "1GHz", but if it's just
> a "suffixed int" with no unit, the name could be changed, I guess.
> 
> But we still have the 1000 vs 1024 problem. On the one hand, it would be
> interesting to make make it consistent and use the same base everywhere.
> On the other hand, I assume we have different command-line options using
> different bases and we'll need to keep compatibility.

If we were to map it to a QAPI schema definition at some point, I'd
imagine it looking something like:

{ 'field_name': { 'type': 'suffixed_int', 'unit': 1000 } }

with 'unit' defaulting to 1024 if unspecified. (I have some patches
floating around as part of the QIDL series for doing more descriptive
QAPI definitions) 

> 
> Must all visitor functions have the
> "function(Visitor *v, obj, const char *name, Error **errp)" signature,
> or can we add additional type-specific arguments? (so we could tell
> the visitor if the default base should be 1000 or 1024)

Visitor functions don't necessarilly have to follow the same basic
signature, so it would be okay to declare it with an extra 'unit' param
and pass that in. We could still hide this behind a visit_type_freq()
wrapper in open-coded visitors as well, I'd just prefer to make the bits
we add to qapi-visit-core.c more general where possible to keep unit
tests and code generation stuff somewhat sane for the core api.

> 
> -- 
> Eduardo
>
Igor Mammedov - Dec. 6, 2012, 8:49 p.m.
On Wed, 5 Dec 2012 15:00:59 -0600
mdroth <mdroth@linux.vnet.ibm.com> wrote:

> On Wed, Dec 05, 2012 at 05:21:50PM -0200, Eduardo Habkost wrote:
> > On Wed, Dec 05, 2012 at 11:52:29AM -0600, mdroth wrote:
> > > On Tue, Dec 04, 2012 at 05:34:42PM -0200, Eduardo Habkost wrote:
> > [...]
> > > > diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
> > > > index 497eb9a..74fe395 100644
> > > > --- a/qapi/string-input-visitor.c
> > > > +++ b/qapi/string-input-visitor.c
> > > > @@ -110,6 +110,27 @@ static void parse_start_optional(Visitor *v, bool *present,
> > > >      *present = true;
> > > >  }
> > > >  
> > > > +static void parse_type_freq(Visitor *v, int64_t *obj, const char *name,
> > > > +                            Error **errp)
> > > > +{
> > > > +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> > > > +    char *endp = (char *) siv->string;
> > > > +    long long val = 0;
> > > > +
> > > > +    errno = 0;
> > > 
> > > If this is for strtosz_suffix_unit(), it looks like this is already
> > > handled internally and can be dropped. Relic from a previous version
> > > that called strtod() directly maybe?
> > > 
> > > If that's not the case, I think it should be fixed in the called function[s]
> > > rather than for each caller.
> > > 
> > > > +    if (siv->string) {
> > > > +        val = strtosz_suffix_unit(siv->string, &endp,
> > > > +                             STRTOSZ_DEFSUFFIX_B, 1000);
> > > 
> > > Specifying 1000 as the unit size will make "1M" == 1000^2 as opposed to
> > > 1024^2. Is this intentional?
> > 
> > I don't know if this is a good idea for a generalx-use visitor, but this is the
> > current behavior of "-cpu ...,tsc_freq=1M", that we need to keep for
> > compatibility, somehow.
> > 
> > > 
> > > > +    }
> > > > +    if (!siv->string || val == -1 || *endp) {
> > > > +        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
> > > > +              "a value representable as a non-negative int64");
> > > > +        return;
> > > > +    }
> > > > +
> > > > +    *obj = val;
> > > > +}
> > > > +
> > > >  Visitor *string_input_get_visitor(StringInputVisitor *v)
> > > >  {
> > > >      return &v->visitor;
> > > > @@ -132,6 +153,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
> > > >      v->visitor.type_str = parse_type_str;
> > > >      v->visitor.type_number = parse_type_number;
> > > >      v->visitor.start_optional = parse_start_optional;
> > > > +    v->visitor.type_freq = parse_type_freq;
> > > 
> > > This seems applicable for stuff like -m 1G and potentionally some other
> > > properties. We can make it generic later, but if we do end up re-spinning
> > > consider something like ->type_unit_suffixed_int(). But I'm not against
> > > leaving as is for now since I can't think of a better name for it atm :)
> > 
> > I thought the visitor was going to support things like "1GHz", but if it's just
> > a "suffixed int" with no unit, the name could be changed, I guess.
> > 
> > But we still have the 1000 vs 1024 problem. On the one hand, it would be
> > interesting to make make it consistent and use the same base everywhere.
> > On the other hand, I assume we have different command-line options using
> > different bases and we'll need to keep compatibility.
> 
> If we were to map it to a QAPI schema definition at some point, I'd
> imagine it looking something like:
> 
> { 'field_name': { 'type': 'suffixed_int', 'unit': 1000 } }
> 
> with 'unit' defaulting to 1024 if unspecified. (I have some patches
> floating around as part of the QIDL series for doing more descriptive
> QAPI definitions) 
> 
> > 
> > Must all visitor functions have the
> > "function(Visitor *v, obj, const char *name, Error **errp)" signature,
> > or can we add additional type-specific arguments? (so we could tell
> > the visitor if the default base should be 1000 or 1024)
> 
> Visitor functions don't necessarilly have to follow the same basic
> signature, so it would be okay to declare it with an extra 'unit' param
> and pass that in. We could still hide this behind a visit_type_freq()
> wrapper in open-coded visitors as well, I'd just prefer to make the bits
> we add to qapi-visit-core.c more general where possible to keep unit
> tests and code generation stuff somewhat sane for the core api.
Lets try to do it this way and if people don't like idea fall back to fixed
type_freq. I'll post patches in a momment

> 
> > 
> > -- 
> > Eduardo
> >

Patch

diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 7a82b63..5c8705e 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -311,3 +311,14 @@  void input_type_enum(Visitor *v, int *obj, const char *strings[],
     g_free(enum_str);
     *obj = value;
 }
+
+void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp)
+{
+    if (!error_is_set(errp)) {
+        if (v->type_freq) {
+            v->type_freq(v, obj, name, errp);
+        } else {
+            v->type_int(v, obj, name, errp);
+        }
+    }
+}
diff --git a/qapi/qapi-visit-core.h b/qapi/qapi-visit-core.h
index 60aceda..e5e7dd7 100644
--- a/qapi/qapi-visit-core.h
+++ b/qapi/qapi-visit-core.h
@@ -62,6 +62,7 @@  struct Visitor
     void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
     /* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
     void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+    void (*type_freq)(Visitor *v, int64_t *obj, const char *name, Error **errp);
 };
 
 void visit_start_handle(Visitor *v, void **obj, const char *kind,
@@ -91,5 +92,6 @@  void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
 void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
 void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
 void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
+void visit_type_freq(Visitor *v, int64_t *obj, const char *name, Error **errp);
 
 #endif
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 497eb9a..74fe395 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -110,6 +110,27 @@  static void parse_start_optional(Visitor *v, bool *present,
     *present = true;
 }
 
+static void parse_type_freq(Visitor *v, int64_t *obj, const char *name,
+                            Error **errp)
+{
+    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+    char *endp = (char *) siv->string;
+    long long val = 0;
+
+    errno = 0;
+    if (siv->string) {
+        val = strtosz_suffix_unit(siv->string, &endp,
+                             STRTOSZ_DEFSUFFIX_B, 1000);
+    }
+    if (!siv->string || val == -1 || *endp) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
+              "a value representable as a non-negative int64");
+        return;
+    }
+
+    *obj = val;
+}
+
 Visitor *string_input_get_visitor(StringInputVisitor *v)
 {
     return &v->visitor;
@@ -132,6 +153,7 @@  StringInputVisitor *string_input_visitor_new(const char *str)
     v->visitor.type_str = parse_type_str;
     v->visitor.type_number = parse_type_number;
     v->visitor.start_optional = parse_start_optional;
+    v->visitor.type_freq = parse_type_freq;
 
     v->string = str;
     return v;