[gtk/a11y/buildable: 1/3] a11y: Add parsing code for accessible values




commit 4ea2a6628f0b4a951ec99b401858fa8bec5d8c7c
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Oct 21 13:22:58 2020 +0100

    a11y: Add parsing code for accessible values
    
    We need to be able to go from a string representation of an accessible
    value to its GtkAccessibleValue instance.

 gtk/gtkaccessiblevalue.c        | 195 +++++++++++++++++++++++++++++++++++++++-
 gtk/gtkaccessiblevalueprivate.h |  24 +++++
 gtk/gtkaccessiblevaluestatic.c  |  92 +++++++++++++++++++
 3 files changed, 307 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkaccessiblevalue.c b/gtk/gtkaccessiblevalue.c
index 2cefba0bc4..45bf824648 100644
--- a/gtk/gtkaccessiblevalue.c
+++ b/gtk/gtkaccessiblevalue.c
@@ -49,6 +49,7 @@
 
 #include <math.h>
 #include <float.h>
+#include <errno.h>
 
 G_DEFINE_QUARK (gtk-accessible-value-error-quark, gtk_accessible_value_error)
 
@@ -637,6 +638,7 @@ typedef struct {
    */
   GCallback ctor;
   GCallback getter;
+  GCallback parser;
 } GtkAccessibleCollect;
 
 static const GtkAccessibleCollect collect_states[] = {
@@ -670,7 +672,8 @@ static const GtkAccessibleCollect collect_states[] = {
     .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
     .name = "invalid",
     .ctor = (GCallback) gtk_invalid_accessible_value_new,
-    .getter = (GCallback) gtk_invalid_accessible_value_get
+    .getter = (GCallback) gtk_invalid_accessible_value_get,
+    .parser = (GCallback) gtk_invalid_accessible_value_parse,
   },
   [GTK_ACCESSIBLE_STATE_PRESSED] = {
     .value = GTK_ACCESSIBLE_STATE_PRESSED,
@@ -691,7 +694,8 @@ static const GtkAccessibleCollect collect_props[] = {
     .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
     .name = "autocomplete",
     .ctor = (GCallback) gtk_autocomplete_accessible_value_new,
-    .getter = (GCallback) gtk_autocomplete_accessible_value_get
+    .getter = (GCallback) gtk_autocomplete_accessible_value_get,
+    .parser = (GCallback) gtk_autocomplete_accessible_value_parse,
   },
   [GTK_ACCESSIBLE_PROPERTY_DESCRIPTION] = {
     .value = GTK_ACCESSIBLE_PROPERTY_DESCRIPTION,
@@ -742,7 +746,8 @@ static const GtkAccessibleCollect collect_props[] = {
     .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN | GTK_ACCESSIBLE_COLLECT_UNDEFINED,
     .name = "orientation",
     .ctor = (GCallback) gtk_orientation_accessible_value_new,
-    .getter = (GCallback) gtk_orientation_accessible_value_get
+    .getter = (GCallback) gtk_orientation_accessible_value_get,
+    .parser = (GCallback) gtk_orientation_accessible_value_parse,
   },
   [GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER] = {
     .value = GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER,
@@ -769,7 +774,8 @@ static const GtkAccessibleCollect collect_props[] = {
     .ctype = GTK_ACCESSIBLE_COLLECT_TOKEN,
     .name = "sort",
     .ctor = (GCallback) gtk_sort_accessible_value_new,
-    .getter = (GCallback) gtk_sort_accessible_value_get
+    .getter = (GCallback) gtk_sort_accessible_value_get,
+    .parser = (GCallback) gtk_sort_accessible_value_parse,
   },
   [GTK_ACCESSIBLE_PROPERTY_VALUE_MAX] = {
     .value = GTK_ACCESSIBLE_PROPERTY_VALUE_MAX,
@@ -896,6 +902,10 @@ typedef GtkAccessibleValue * (* GtkAccessibleValueStringCtor)   (const char *val
 typedef GtkAccessibleValue * (* GtkAccessibleValueRefCtor)      (GtkAccessible *value);
 typedef GtkAccessibleValue * (* GtkAccessibleValueRefListCtor)  (GList *value);
 
+typedef GtkAccessibleValue * (* GtkAccessibleValueEnumParser)   (const char  *str,
+                                                                 gsize        len,
+                                                                 GError     **error);
+
 /*< private >
  * gtk_accessible_value_get_default_for_state:
  * @state: a #GtkAccessibleState
@@ -1314,6 +1324,144 @@ gtk_accessible_value_collect_value (const GtkAccessibleCollect  *cstate,
   return res;
 }
 
+static GtkAccessibleValue *
+gtk_accessible_value_parse (const GtkAccessibleCollect  *cstate,
+                            const char                  *str,
+                            gsize                        len,
+                            GError                     **error)
+{
+  GtkAccessibleValue *res = NULL;
+  GtkAccessibleCollectType ctype = cstate->ctype;
+  gboolean collects_undef = (ctype & GTK_ACCESSIBLE_COLLECT_UNDEFINED) != 0;
+
+  ctype &= (GTK_ACCESSIBLE_COLLECT_UNDEFINED - 1);
+
+  /* Tristate values include "undefined" by definition */
+  if (ctype == GTK_ACCESSIBLE_COLLECT_TRISTATE)
+    collects_undef = TRUE;
+
+  switch (ctype)
+    {
+    case GTK_ACCESSIBLE_COLLECT_BOOLEAN:
+      {
+        if (strncmp (str, "true", 4) == 0)
+          res = gtk_boolean_accessible_value_new (TRUE);
+        else if (strncmp (str, "false", 5) == 0)
+          res = gtk_boolean_accessible_value_new (FALSE);
+        else if (collects_undef && strncmp (str, "undefined", 9) == 0)
+          res = gtk_undefined_accessible_value_new ();
+        else
+          g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                       GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
+                       "Invalid token “%s” for boolean attribute",
+                       str);
+      }
+      break;
+
+    case GTK_ACCESSIBLE_COLLECT_TRISTATE:
+      {
+        if (strncmp (str, "true", 4) == 0)
+          res = gtk_tristate_accessible_value_new (GTK_ACCESSIBLE_TRISTATE_TRUE);
+        else if (strncmp (str, "false", 5) == 0)
+          res = gtk_tristate_accessible_value_new (GTK_ACCESSIBLE_TRISTATE_FALSE);
+        else if (strncmp (str, "mixed", 5) == 0)
+          res = gtk_tristate_accessible_value_new (GTK_ACCESSIBLE_TRISTATE_MIXED);
+        else if (collects_undef && strncmp (str, "undefined", 9) == 0)
+          res = gtk_undefined_accessible_value_new ();
+        else
+          {
+            g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                         GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
+                         "Invalid token “%s” for tristate attribute",
+                         str);
+            return NULL;
+          }
+      }
+      break;
+
+    case GTK_ACCESSIBLE_COLLECT_TOKEN:
+      {
+        GtkAccessibleValueEnumParser parser =
+          (GtkAccessibleValueEnumParser) cstate->parser;
+
+        if (collects_undef && strncmp (str, "undefined", 9) == 0)
+          {
+            res = gtk_undefined_accessible_value_new ();
+          }
+        else
+          {
+            /* Token collection requires a constructor */
+            g_assert (parser != NULL);
+
+            res = (* parser) (str, len, error);
+          }
+      }
+      break;
+
+    case GTK_ACCESSIBLE_COLLECT_INTEGER:
+      {
+        char *end = NULL;
+        gint64 value = g_ascii_strtoll (str, &end, 10);
+
+        if (str == end)
+          {
+            int saved_errno = errno;
+            g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                         GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
+                         "Invalid integer value “%s”: %s",
+                         str, g_strerror (saved_errno));
+
+            return NULL;
+          }
+        else
+          res = gtk_int_accessible_value_new ((int) value);
+      }
+      break;
+
+    case GTK_ACCESSIBLE_COLLECT_NUMBER:
+      {
+        char *end = NULL;
+        double value = g_ascii_strtod (str, &end);
+
+        if (str == end || isnan (value) || isinf (value))
+          {
+            g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                         GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
+                         "Invalid numeric value “%s”",
+                         str);
+            return NULL;
+          }
+
+        res = gtk_number_accessible_value_new (value);
+      }
+      break;
+
+    case GTK_ACCESSIBLE_COLLECT_STRING:
+      {
+        res = gtk_string_accessible_value_new (str);
+      }
+      break;
+
+    case GTK_ACCESSIBLE_COLLECT_REFERENCE:
+    case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
+      {
+        res = NULL;
+        g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                     GTK_ACCESSIBLE_VALUE_ERROR_INVALID_VALUE,
+                     "Invalid relation “%s”",
+                     str);
+      }
+      break;
+
+    case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
+    case GTK_ACCESSIBLE_COLLECT_INVALID:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return res;
+}
 /*< private >
  * gtk_accessible_value_collect_for_state:
  * @state: a #GtkAccessibleState
@@ -1370,6 +1518,19 @@ gtk_accessible_value_collect_for_state_value (GtkAccessibleState   state,
   return gtk_accessible_value_collect_value (cstate, value, error);
 }
 
+GtkAccessibleValue *
+gtk_accessible_value_parse_for_state (GtkAccessibleState   state,
+                                      const char          *str,
+                                      gsize                len,
+                                      GError             **error)
+{
+  const GtkAccessibleCollect *cstate = &collect_states[state];
+
+  g_return_val_if_fail (state <= GTK_ACCESSIBLE_STATE_SELECTED, NULL);
+
+  return gtk_accessible_value_parse (cstate, str, len, error);
+}
+
 /*< private >
  * gtk_accessible_value_get_default_for_property:
  * @property: a #GtkAccessibleProperty
@@ -1487,6 +1648,19 @@ gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty   propert
   return gtk_accessible_value_collect_value (cstate, value, error);
 }
 
+GtkAccessibleValue *
+gtk_accessible_value_parse_for_property (GtkAccessibleProperty   property,
+                                         const char             *str,
+                                         gsize                   len,
+                                         GError                **error)
+{
+  const GtkAccessibleCollect *cstate = &collect_props[property];
+
+  g_return_val_if_fail (property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT, NULL);
+
+  return gtk_accessible_value_parse (cstate, str, len, error);
+}
+
 /*< private >
  * gtk_accessible_value_get_default_for_relation:
  * @relation: a #GtkAccessibleRelation
@@ -1596,4 +1770,17 @@ gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation   relatio
   return gtk_accessible_value_collect_value (cstate, value, error);
 }
 
+GtkAccessibleValue *
+gtk_accessible_value_parse_for_relation (GtkAccessibleRelation   relation,
+                                         const char             *str,
+                                         gsize                   len,
+                                         GError                **error)
+{
+  const GtkAccessibleCollect *cstate = &collect_rels[relation];
+
+  g_return_val_if_fail (relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE, NULL);
+
+  return gtk_accessible_value_parse (cstate, str, len, error);
+}
+
 /* }}} */
diff --git a/gtk/gtkaccessiblevalueprivate.h b/gtk/gtkaccessiblevalueprivate.h
index 073b2c2c45..3290fc1e6e 100644
--- a/gtk/gtkaccessiblevalueprivate.h
+++ b/gtk/gtkaccessiblevalueprivate.h
@@ -98,6 +98,10 @@ GtkAccessibleValue *    gtk_accessible_value_collect_for_state          (GtkAcce
 GtkAccessibleValue *    gtk_accessible_value_collect_for_state_value    (GtkAccessibleState             
state,
                                                                          const GValue                  
*value,
                                                                          GError                       
**error);
+GtkAccessibleValue *    gtk_accessible_value_parse_for_state            (GtkAccessibleState             
state,
+                                                                         const char                    *str,
+                                                                         gsize                          len,
+                                                                         GError                       
**error);
 
 GtkAccessibleValue *    gtk_accessible_value_get_default_for_property   (GtkAccessibleProperty          
property);
 GtkAccessibleValue *    gtk_accessible_value_collect_for_property       (GtkAccessibleProperty          
property,
@@ -106,6 +110,10 @@ GtkAccessibleValue *    gtk_accessible_value_collect_for_property       (GtkAcce
 GtkAccessibleValue *    gtk_accessible_value_collect_for_property_value (GtkAccessibleProperty          
property,
                                                                          const GValue                  
*value,
                                                                          GError                       
**error);
+GtkAccessibleValue *    gtk_accessible_value_parse_for_property         (GtkAccessibleProperty          
property,
+                                                                         const char                    *str,
+                                                                         gsize                          len,
+                                                                         GError                       
**error);
 
 GtkAccessibleValue *    gtk_accessible_value_get_default_for_relation   (GtkAccessibleRelation          
relation);
 GtkAccessibleValue *    gtk_accessible_value_collect_for_relation       (GtkAccessibleRelation          
relation,
@@ -114,6 +122,10 @@ GtkAccessibleValue *    gtk_accessible_value_collect_for_relation       (GtkAcce
 GtkAccessibleValue *    gtk_accessible_value_collect_for_relation_value (GtkAccessibleRelation          
relation,
                                                                          const GValue                  
*value,
                                                                          GError                       
**error);
+GtkAccessibleValue *    gtk_accessible_value_parse_for_relation         (GtkAccessibleRelation          
relation,
+                                                                         const char                    *str,
+                                                                         gsize                          len,
+                                                                         GError                       
**error);
 
 /* Basic values */
 GtkAccessibleValue *            gtk_undefined_accessible_value_new      (void);
@@ -143,14 +155,26 @@ GList *                         gtk_reference_list_accessible_value_get (const G
 /* Token values */
 GtkAccessibleValue *            gtk_invalid_accessible_value_new        (GtkAccessibleInvalidState value);
 GtkAccessibleInvalidState       gtk_invalid_accessible_value_get        (const GtkAccessibleValue *value);
+GtkAccessibleValue *            gtk_invalid_accessible_value_parse      (const char               *str,
+                                                                         gsize                     len,
+                                                                         GError                  **error);
 
 GtkAccessibleValue *            gtk_autocomplete_accessible_value_new   (GtkAccessibleAutocomplete value);
 GtkAccessibleAutocomplete       gtk_autocomplete_accessible_value_get   (const GtkAccessibleValue *value);
+GtkAccessibleValue *            gtk_autocomplete_accessible_value_parse (const char               *str,
+                                                                         gsize                     len,
+                                                                         GError                  **error);
 
 GtkAccessibleValue *            gtk_orientation_accessible_value_new    (GtkOrientation            value);
 GtkOrientation                  gtk_orientation_accessible_value_get    (const GtkAccessibleValue *value);
+GtkAccessibleValue *            gtk_orientation_accessible_value_parse  (const char               *str,
+                                                                         gsize                     len,
+                                                                         GError                  **error);
 
 GtkAccessibleValue *            gtk_sort_accessible_value_new           (GtkAccessibleSort         value);
 GtkAccessibleSort               gtk_sort_accessible_value_get           (const GtkAccessibleValue *value);
+GtkAccessibleValue *            gtk_sort_accessible_value_parse         (const char               *str,
+                                                                         gsize                     len,
+                                                                         GError                  **error);
 
 G_END_DECLS
diff --git a/gtk/gtkaccessiblevaluestatic.c b/gtk/gtkaccessiblevaluestatic.c
index 6d26ea2900..5cb761eba5 100644
--- a/gtk/gtkaccessiblevaluestatic.c
+++ b/gtk/gtkaccessiblevaluestatic.c
@@ -282,6 +282,30 @@ gtk_invalid_accessible_value_get (const GtkAccessibleValue *value)
   return self->value;
 }
 
+GtkAccessibleValue *
+gtk_invalid_accessible_value_parse (const char  *str,
+                                    gsize        len,
+                                    GError     **error)
+{
+  g_return_val_if_fail (str == NULL || len == 0, NULL);
+
+  if (strncmp (str, "false", 5) == 0)
+    return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_FALSE);
+  else if (strncmp (str, "true", 4) == 0)
+    return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_TRUE);
+  else if (strncmp (str, "grammar", 7) == 0)
+    return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_GRAMMAR);
+  else if (strncmp (str, "spelling", 8) == 0)
+    return gtk_invalid_accessible_value_new (GTK_ACCESSIBLE_INVALID_SPELLING);
+  else
+    g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                 GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
+                 "Unknown token “%s”",
+                 str);
+
+  return NULL;
+}
+
 static const GtkAccessibleValueClass GTK_AUTOCOMPLETE_ACCESSIBLE_VALUE = {
   .type = GTK_ACCESSIBLE_VALUE_TYPE_TOKEN,
   .type_name = "GtkAutocompleteAccessibleValue",
@@ -327,6 +351,30 @@ gtk_autocomplete_accessible_value_get (const GtkAccessibleValue *value)
   return self->value;
 }
 
+GtkAccessibleValue *
+gtk_autocomplete_accessible_value_parse (const char  *str,
+                                         gsize        len,
+                                         GError     **error)
+{
+  g_return_val_if_fail (str == NULL || len == 0, NULL);
+
+  if (strncmp (str, "none", 4) == 0)
+    return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_NONE);
+  else if (strncmp (str, "inline", 6) == 0)
+    return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_INLINE);
+  else if (strncmp (str, "list", 4) == 0)
+    return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_LIST);
+  else if (strncmp (str, "both", 4) == 0)
+    return gtk_autocomplete_accessible_value_new (GTK_ACCESSIBLE_AUTOCOMPLETE_BOTH);
+  else
+    g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                 GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
+                 "Unknown token “%s”",
+                 str);
+
+  return NULL;
+}
+
 static const GtkAccessibleValueClass GTK_ORIENTATION_ACCESSIBLE_VALUE = {
   .type = GTK_ACCESSIBLE_VALUE_TYPE_TOKEN,
   .type_name = "GtkOrientationAccessibleValue",
@@ -366,6 +414,26 @@ gtk_orientation_accessible_value_get (const GtkAccessibleValue *value)
   return self->value;
 }
 
+GtkAccessibleValue *
+gtk_orientation_accessible_value_parse (const char  *str,
+                                        gsize        len,
+                                        GError     **error)
+{
+  g_return_val_if_fail (str == NULL || len == 0, NULL);
+
+  if (strncmp (str, "horizontal", 10) == 0)
+    return gtk_orientation_accessible_value_new (GTK_ORIENTATION_HORIZONTAL);
+  else if (strncmp (str, "vertical", 8) == 0)
+    return gtk_orientation_accessible_value_new (GTK_ORIENTATION_VERTICAL);
+  else
+    g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                 GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
+                 "Unknown token “%s”",
+                 str);
+
+  return NULL;
+}
+
 static const GtkAccessibleValueClass GTK_SORT_ACCESSIBLE_VALUE = {
   .type = GTK_ACCESSIBLE_VALUE_TYPE_TOKEN,
   .type_name = "GtkSortAccessibleValue",
@@ -411,4 +479,28 @@ gtk_sort_accessible_value_get (const GtkAccessibleValue *value)
   return self->value;
 }
 
+GtkAccessibleValue *
+gtk_sort_accessible_value_parse (const char  *str,
+                                 gsize        len,
+                                 GError     **error)
+{
+  g_return_val_if_fail (str == NULL || len == 0, NULL);
+
+  if (strncmp (str, "none", 4) == 0)
+    return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_NONE);
+  else if (strncmp (str, "ascending", 9) == 0)
+    return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_ASCENDING);
+  else if (strncmp (str, "descending", 10) == 0)
+    return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_DESCENDING);
+  else if (strncmp (str, "other", 5) == 0)
+    return gtk_sort_accessible_value_new (GTK_ACCESSIBLE_SORT_OTHER);
+  else
+    g_set_error (error, GTK_ACCESSIBLE_VALUE_ERROR,
+                 GTK_ACCESSIBLE_VALUE_ERROR_INVALID_TOKEN,
+                 "Unknown token “%s”",
+                 str);
+
+  return NULL;
+}
+
 /* }}} */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]