[waffle] [PATCH 3/4] waffle: add waffle_string_to_enum()

Emil Velikov emil.l.velikov at gmail.com
Thu Apr 23 02:02:09 PDT 2015


On 22 April 2015 at 19:03, Frank Henigman <fjhenigman at google.com> wrote:
> From: Frank Henigman <fjhenigman at gmail.com>
>
> Add waffle_string_to_enum() which, given a string, returns the
> corresponding enum value.
> Since the main use is expected to be parsing command lines,
> the string case does not have to match, and some aliases exist.
> For example "waffle_context_opengles2" will match WAFFLE_CONTEXT_OPENGL_ES2
> (note additional underscore in the enum name).
>
> Signed-off-by: Frank Henigman <fjhenigman at google.com>
> ---
>  include/waffle/waffle.h      |  5 +++++
>  man/waffle_enum.3.xml        | 24 ++++++++++++++++++++++++
>  src/waffle/api/waffle_enum.c |  7 +++++++
>  src/waffle/core/wcore_util.c | 36 ++++++++++++++++++++++++++++++++++++
>  src/waffle/core/wcore_util.h |  3 +++
>  src/waffle/waffle.def.in     |  1 +
>  6 files changed, 76 insertions(+)
>
> diff --git a/include/waffle/waffle.h b/include/waffle/waffle.h
> index dd39f2c..8822e34 100644
> --- a/include/waffle/waffle.h
> +++ b/include/waffle/waffle.h
> @@ -189,6 +189,11 @@ WAFFLE_ENUM_LIST(ENUM_ITEM)
>  const char*
>  waffle_enum_to_string(int32_t e);
>
> +#if WAFFLE_API_VERSION >= 0x0106
> +bool
> +waffle_string_to_enum(const char *s, int32_t *e);
> +#endif
> +
>  // ---------------------------------------------------------------------------
>
>  bool
> diff --git a/man/waffle_enum.3.xml b/man/waffle_enum.3.xml
> index 4874fe7..4b08a04 100644
> --- a/man/waffle_enum.3.xml
> +++ b/man/waffle_enum.3.xml
> @@ -23,6 +23,7 @@
>    <refnamediv>
>      <refname>waffle_enum</refname>
>      <refname>waffle_enum_to_string</refname>
> +    <refname>waffle_string_to_enum</refname>
>      <refpurpose>Listing of non-error enums and associated utility functions</refpurpose>
>    </refnamediv>
>
> @@ -49,6 +50,12 @@ enum waffle_enum {...};
>          <paramdef>int32_t <parameter>e</parameter></paramdef>
>        </funcprototype>
>
> +      <funcprototype>
> +        <funcdef>bool <function>waffle_string_to_enum</function></funcdef>
> +        <paramdef>const char* <parameter>s</parameter></paramdef>
> +        <paramdef>int32_t* <parameter>e</parameter></paramdef>
> +      </funcprototype>
> +
>      </funcsynopsis>
>    </refsynopsisdiv>
>
> @@ -74,6 +81,23 @@ enum waffle_enum {...};
>        </varlistentry>
>
>        <varlistentry>
> +        <term><function>waffle_string_to_enum()</function></term>
> +        <listitem>
> +          <para>
> +            Convert a string to a <type>waffle_enum</type> token in <code>*e</code>.
> +            For example, convert <code>"WAFFLE_DONT_CARE"</code> to <constant>WAFFLE_DONT_CARE</constant>.
> +            String matching is not case-sensitive, and aliases exist for some names.
> +            Returns <constant>false</constant> and does not change <code>*e</code> if the string does not match any <type>waffle_enum</type> name.
> +          </para>
> +          <para>
> +            This function always sets the error code to <constant>WAFFLE_NO_ERROR</constant>.
> +            It can be called before waffle has been successfully initialized with
> +            <citerefentry><refentrytitle><function>waffle_init</function></refentrytitle><manvolnum>3</manvolnum></citerefentry>
Very nicely written.

> +          </para>
> +        </listitem>
> +      </varlistentry>
> +
> +      <varlistentry>
>          <term><type>enum waffle_enum</type></term>
>          <listitem>
>            <para>
> diff --git a/src/waffle/api/waffle_enum.c b/src/waffle/api/waffle_enum.c
> index 1b8dfbb..d49ce5e 100644
> --- a/src/waffle/api/waffle_enum.c
> +++ b/src/waffle/api/waffle_enum.c
> @@ -34,3 +34,10 @@ waffle_enum_to_string(int32_t e)
>      wcore_error_reset();
>      return wcore_enum_to_string(e);
>  }
> +
> +WAFFLE_API bool
> +waffle_string_to_enum(const char *s, int32_t *e)
> +{
> +    wcore_error_reset();
> +    return wcore_string_to_enum(s, e);
> +}
> diff --git a/src/waffle/core/wcore_util.c b/src/waffle/core/wcore_util.c
> index b912a30..80b66f9 100644
> --- a/src/waffle/core/wcore_util.c
> +++ b/src/waffle/core/wcore_util.c
> @@ -24,6 +24,7 @@
>  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>
>  #include <stdlib.h>
> +#include <string.h>
>
>  #include "wcore_error.h"
>  #include "wcore_util.h"
> @@ -74,6 +75,14 @@ struct enum_map_entry {
>  };
>
>  static int
> +enum_cmp_name(const void *v1, const void *v2)
> +{
> +    const struct enum_map_entry *e1 = (const struct enum_map_entry *) v1;
> +    const struct enum_map_entry *e2 = (const struct enum_map_entry *) v2;
> +    return strcasecmp(e1->name, e2->name);
How would waffle handle cases where one feeds in a non-null terminated
character array ?
I'm assuming that strncasecmp might help although surely there is a better way.

> +}
> +
> +static int
>  enum_cmp_value(const void *v1, const void *v2)
>  {
>      const struct enum_map_entry *e1 = (const struct enum_map_entry *) v1;
> @@ -83,6 +92,14 @@ enum_cmp_value(const void *v1, const void *v2)
>
>  #define NAME_VALUE(name, value) { #name, value },
>
> +static struct enum_map_entry enum_map_name[] = {
> +    WAFFLE_ENUM_LIST(NAME_VALUE)
> +    // aliases
> +    { "WAFFLE_CONTEXT_OPENGLES1", WAFFLE_CONTEXT_OPENGL_ES1 },
> +    { "WAFFLE_CONTEXT_OPENGLES2", WAFFLE_CONTEXT_OPENGL_ES2 },
> +    { "WAFFLE_CONTEXT_OPENGLES3", WAFFLE_CONTEXT_OPENGL_ES3 },
What inspired you to add these aliases - was it wflinfo ? No
objections here (actually I think it's a very nice idea) just curios.

> +};
> +
>  static struct enum_map_entry enum_map_value[] = {
>      WAFFLE_ENUM_LIST(NAME_VALUE)
>  };
> @@ -97,6 +114,8 @@ enum_sort()
>      static bool sorted = false;
>      if (sorted)
>          return;
> +    qsort(enum_map_name, ARRAY_SIZE(enum_map_name), sizeof(enum_map_name[0]),
> +          enum_cmp_name);
Same comment as in patch 2 applies here. Let's not do the sorting at runtime.

>      qsort(enum_map_value, ARRAY_SIZE(enum_map_value), sizeof(enum_map_value[0]),
>            enum_cmp_value);
>      sorted = true;
> @@ -118,4 +137,21 @@ wcore_enum_to_string(int32_t e)
>      return found->name;
>  }
>
> +bool
> +wcore_string_to_enum(const char *s, int32_t *e)
> +{
> +    enum_sort();
> +    struct enum_map_entry key = { .name = s };
> +    struct enum_map_entry *found = bsearch(&key,
> +                                           enum_map_name,
> +                                           ARRAY_SIZE(enum_map_name),
> +                                           sizeof(enum_map_name[0]),
> +                                           enum_cmp_name);
Ditto.

> +    if (!found)
> +        return false;
> +
> +    *e = found->value;
> +    return true;
> +}
> +
>  #undef ARRAY_SIZE
> diff --git a/src/waffle/core/wcore_util.h b/src/waffle/core/wcore_util.h
> index b823b21..21c2a88 100644
> --- a/src/waffle/core/wcore_util.h
> +++ b/src/waffle/core/wcore_util.h
> @@ -112,6 +112,9 @@ wcore_calloc(size_t size);
>  const char*
>  wcore_enum_to_string(int32_t e);
>
> +bool
> +wcore_string_to_enum(const char *s, int32_t *e);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/src/waffle/waffle.def.in b/src/waffle/waffle.def.in
> index 75a56c0..7726219 100644
> --- a/src/waffle/waffle.def.in
> +++ b/src/waffle/waffle.def.in
> @@ -5,6 +5,7 @@ EXPORTS
>      waffle_error_get_info
>      waffle_error_to_string
>      waffle_enum_to_string
> +    waffle_string_to_enum
Thank you for this one.

-Emil


More information about the waffle mailing list