[gnome-builder/wip/chergert/debugger: 23/100] mi2: use gvariant to parse protocol data from gdb



commit 15d0c11b7b1448e170fcc91186bfe03152ee5f8b
Author: Christian Hergert <chergert redhat com>
Date:   Thu Mar 23 21:46:49 2017 -0700

    mi2: use gvariant to parse protocol data from gdb

 contrib/mi2/mi2-message.c       |   57 ++++++++++++++-
 contrib/mi2/mi2-message.h       |    5 ++
 contrib/mi2/mi2-reply-message.c |   40 +++++++++-
 contrib/mi2/mi2-util.c          |  150 ++++++++++++++++++++++++++++++++++++++-
 contrib/mi2/mi2-util.h          |   12 ++-
 5 files changed, 249 insertions(+), 15 deletions(-)
---
diff --git a/contrib/mi2/mi2-message.c b/contrib/mi2/mi2-message.c
index 5d3ac0c..4c9c3b2 100644
--- a/contrib/mi2/mi2-message.c
+++ b/contrib/mi2/mi2-message.c
@@ -33,6 +33,12 @@ typedef struct
 
 G_DEFINE_TYPE_WITH_PRIVATE (Mi2Message, mi2_message, G_TYPE_OBJECT)
 
+static GHashTable *
+make_hashtable (void)
+{
+  return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
+}
+
 static void
 mi2_message_finalize (GObject *object)
 {
@@ -128,13 +134,14 @@ mi2_message_get_param_string (Mi2Message  *self,
                               const gchar *name)
 {
   Mi2MessagePrivate *priv = mi2_message_get_instance_private (self);
+  GVariant *variant = NULL;
 
   g_return_val_if_fail (MI2_IS_MESSAGE (self), NULL);
 
   if (priv->params != NULL)
-    return g_hash_table_lookup (priv->params, name);
+    variant = g_hash_table_lookup (priv->params, name);
 
-  return NULL;
+  return variant == NULL ? NULL : g_variant_get_string (variant, NULL);
 }
 
 void
@@ -148,8 +155,50 @@ mi2_message_set_param_string (Mi2Message  *self,
   g_return_if_fail (name != NULL);
 
   if (priv->params == NULL)
-    priv->params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-  g_hash_table_insert (priv->params, g_strdup (name), g_strdup (value));
+    priv->params = make_hashtable ();
+
+  if (value == NULL)
+    g_hash_table_remove (priv->params, name);
+  else
+    g_hash_table_insert (priv->params,
+                         g_strdup (name),
+                         g_variant_ref_sink (g_variant_new_string (value)));
+}
+
+GVariant *
+mi2_message_get_param (Mi2Message  *self,
+                       const gchar *param)
+{
+  Mi2MessagePrivate *priv = mi2_message_get_instance_private (self);
+
+  g_return_val_if_fail (MI2_IS_MESSAGE (self), NULL);
+  g_return_val_if_fail (param != NULL, NULL);
+
+  if (priv->params)
+    return g_hash_table_lookup (priv->params, param);
+
+  return NULL;
+}
+
+void
+mi2_message_set_param (Mi2Message  *self,
+                       const gchar *param,
+                       GVariant    *variant)
+{
+  Mi2MessagePrivate *priv = mi2_message_get_instance_private (self);
+
+  g_return_if_fail (MI2_IS_MESSAGE (self));
+  g_return_if_fail (param != NULL);
+
+  if (priv->params == NULL)
+    priv->params = make_hashtable ();
+
+  if (variant == NULL)
+    g_hash_table_remove (priv->params, param);
+  else
+    g_hash_table_insert (priv->params,
+                         g_strdup (param),
+                         g_variant_ref_sink (variant));
 }
 
 /**
diff --git a/contrib/mi2/mi2-message.h b/contrib/mi2/mi2-message.h
index 261e866..dece0b7 100644
--- a/contrib/mi2/mi2-message.h
+++ b/contrib/mi2/mi2-message.h
@@ -48,6 +48,11 @@ Mi2Message   *mi2_message_parse            (const gchar  *line,
                                             GError      **error);
 GBytes       *mi2_message_serialize        (Mi2Message   *self);
 const gchar **mi2_message_get_params       (Mi2Message   *self);
+GVariant     *mi2_message_get_param        (Mi2Message   *self,
+                                            const gchar  *param);
+void          mi2_message_set_param        (Mi2Message   *self,
+                                            const gchar  *param,
+                                            GVariant     *variant);
 const gchar  *mi2_message_get_param_string (Mi2Message   *self,
                                             const gchar  *name);
 void          mi2_message_set_param_string (Mi2Message   *self,
diff --git a/contrib/mi2/mi2-reply-message.c b/contrib/mi2/mi2-reply-message.c
index d941bdd..cb5209c 100644
--- a/contrib/mi2/mi2-reply-message.c
+++ b/contrib/mi2/mi2-reply-message.c
@@ -130,13 +130,45 @@ mi2_reply_message_new_from_string (const gchar *line)
       while (line != NULL && *line != '\0')
         {
           g_autofree gchar *key = NULL;
-          g_autofree gchar *value = NULL;
 
-          if (!(key = mi2_util_parse_word (line, &line)) ||
-              !(value = mi2_util_parse_string (line, &line)))
+          if (*line == ',')
+            line++;
+
+          key = mi2_util_parse_word (line, &line);
+          if (key == NULL)
             break;
 
-          mi2_message_set_param_string (MI2_MESSAGE (ret), key, value);
+          if (*line == '=')
+            line++;
+
+          if (*line == '"')
+            {
+              g_autofree gchar *value = NULL;
+
+              value = mi2_util_parse_string (line, &line);
+              mi2_message_set_param_string (MI2_MESSAGE (ret), key, value);
+              continue;
+            }
+          else if (*line == '{')
+            {
+              g_autoptr(GVariant) variant = NULL;
+
+              variant = mi2_util_parse_record (line, &line);
+              mi2_message_set_param (MI2_MESSAGE (ret), key, variant);
+              continue;
+            }
+          else if (*line == '[')
+            {
+              g_autoptr(GVariant) variant = NULL;
+
+              variant = mi2_util_parse_list (line, &line);
+              mi2_message_set_param (MI2_MESSAGE (ret), key, variant);
+              continue;
+            }
+
+          g_warning ("Failed to parse: %s\n", line);
+
+          break;
         }
     }
 
diff --git a/contrib/mi2/mi2-util.c b/contrib/mi2/mi2-util.c
index a279784..f5cefc6 100644
--- a/contrib/mi2/mi2-util.c
+++ b/contrib/mi2/mi2-util.c
@@ -101,11 +101,155 @@ mi2_util_parse_word (const gchar  *line,
 
   ret = g_strndup (begin, line - begin);
 
-  if (*line)
-    line++;
-
   if (endptr)
     *endptr = line;
 
   return ret;
 }
+
+GVariant *
+mi2_util_parse_record (const gchar *line,
+                       const gchar **endptr)
+{
+  GVariantDict dict;
+
+  g_return_val_if_fail (line != NULL, NULL);
+  g_return_val_if_fail (*line == '{', NULL);
+
+  g_variant_dict_init (&dict, NULL);
+
+  /* move past { */
+  line++;
+
+  while (*line != '}')
+    {
+      g_autofree gchar *key = NULL;
+
+      if (*line == ',')
+        line++;
+
+      if (!(key = mi2_util_parse_word (line, &line)))
+        goto failure;
+
+      if (*line == '=')
+        line++;
+
+      if (*line == '"')
+        {
+          g_autofree gchar *value = NULL;
+
+          if (!(value = mi2_util_parse_string (line, &line)))
+            goto failure;
+
+          g_variant_dict_insert (&dict, key, "s", value);
+        }
+      else if (*line == '{')
+        {
+          g_autoptr(GVariant) v = NULL;
+
+          if (!(v = mi2_util_parse_record (line, &line)))
+            goto failure;
+
+          g_variant_dict_insert_value (&dict, key, v);
+        }
+      else if (*line == '[')
+        {
+          g_autoptr(GVariant) ar = NULL;
+
+          if (!(ar = mi2_util_parse_list (line, &line)))
+            goto failure;
+
+          g_variant_dict_insert_value (&dict, key, ar);
+        }
+      else
+        goto failure;
+
+      if (*line == ',')
+        line++;
+    }
+
+  g_assert (*line == '}');
+
+  line++;
+
+  if (endptr)
+    *endptr = line;
+
+  return g_variant_ref_sink (g_variant_dict_end (&dict));
+
+failure:
+  g_variant_dict_clear (&dict);
+  if (endptr)
+    *endptr = NULL;
+  return NULL;
+}
+
+GVariant *
+mi2_util_parse_list (const gchar  *line,
+                     const gchar **endptr)
+{
+  GVariantBuilder builder;
+
+  g_return_val_if_fail (line != NULL, NULL);
+  g_return_val_if_fail (*line == '[', NULL);
+
+  /* move past [ */
+  line++;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
+  g_variant_builder_open (&builder, G_VARIANT_TYPE ("v"));
+
+  while (*line != ']')
+    {
+      if (*line == '"')
+        {
+          g_autofree gchar *value = NULL;
+
+          if (!(value = mi2_util_parse_string (line, &line)))
+            goto failure;
+
+          g_variant_builder_add (&builder, "s", value);
+        }
+      else if (*line == '{')
+        {
+          g_autoptr(GVariant) v = NULL;
+
+          if (!(v = mi2_util_parse_record (line, &line)))
+            goto failure;
+
+          g_variant_builder_add_value (&builder, v);
+        }
+      else if (*line == '[')
+        {
+          g_autoptr(GVariant) ar = NULL;
+
+          if (!(ar = mi2_util_parse_list (line, &line)))
+            goto failure;
+
+          g_variant_builder_add_value (&builder, ar);
+        }
+      else
+        goto failure;
+
+
+      if (*line == ',')
+        line++;
+    }
+
+  g_assert (*line == ']');
+
+  line++;
+
+  if (endptr)
+    *endptr = line;
+
+  g_variant_builder_close (&builder);
+
+  return g_variant_ref_sink (g_variant_builder_end (&builder));
+
+failure:
+  g_variant_builder_clear (&builder);
+  if (endptr)
+    *endptr = NULL;
+  return NULL;
+}
diff --git a/contrib/mi2/mi2-util.h b/contrib/mi2/mi2-util.h
index da32968..e4bd582 100644
--- a/contrib/mi2/mi2-util.h
+++ b/contrib/mi2/mi2-util.h
@@ -23,10 +23,14 @@
 
 G_BEGIN_DECLS
 
-gchar *mi2_util_parse_string (const gchar  *line,
-                              const gchar **endptr);
-gchar *mi2_util_parse_word   (const gchar  *line,
-                              const gchar **endptr);
+gchar    *mi2_util_parse_string (const gchar  *line,
+                                 const gchar **endptr);
+gchar    *mi2_util_parse_word   (const gchar  *line,
+                                 const gchar **endptr);
+GVariant *mi2_util_parse_record (const gchar  *line,
+                                 const gchar **endptr);
+GVariant *mi2_util_parse_list   (const gchar  *line,
+                                 const gchar **endptr);
 
 G_END_DECLS
 


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