[gtk/wip/otte/json: 20/21] jsonparser: Add some convenience API




commit 2a9e757c7e2d4360fd0bc43474cf7be017a28e42
Author: Benjamin Otte <otte redhat com>
Date:   Sun Dec 5 22:07:38 2021 +0100

    jsonparser: Add some convenience API
    
    gtk_json_parser_rewind()
    Allows to reread the current object/array.
    
    gtk_json_parser_has_member()
    Checks the name of the current member.
    
    gtk_json_parser_find_member()
    Finds the member with the given name (or forwards to end of document and
    returns FALSE);

 gtk/json/gtkjsonparser.c        | 116 +++++++++++++++++++++++++++++++++-------
 gtk/json/gtkjsonparserprivate.h |   5 ++
 2 files changed, 102 insertions(+), 19 deletions(-)
---
diff --git a/gtk/json/gtkjsonparser.c b/gtk/json/gtkjsonparser.c
index dd8d4e95f4..e82d974d31 100644
--- a/gtk/json/gtkjsonparser.c
+++ b/gtk/json/gtkjsonparser.c
@@ -980,16 +980,7 @@ gtk_json_parser_new_for_bytes (GBytes *bytes)
 
   gtk_json_parser_skip_bom (self);
   self->start = self->reader;
-  gtk_json_parser_skip_whitespace (self);
-  if (gtk_json_parser_is_eof (self))
-    {
-      gtk_json_parser_syntax_error_at (self, self->start, self->reader, "Empty document");
-    }
-  else
-    {
-      self->block->value = self->reader;
-      gtk_json_parser_parse_value (self);
-    }
+  gtk_json_parser_rewind (self);
 
   return self;
 }
@@ -1162,6 +1153,46 @@ gtk_json_parser_next (GtkJsonParser *self)
   return TRUE;
 }
 
+void
+gtk_json_parser_rewind (GtkJsonParser *self)
+{
+  if (self->error)
+    return;
+
+  switch (self->block->type)
+    {
+    case GTK_JSON_BLOCK_OBJECT:
+      gtk_json_parser_pop_block (self);
+      self->reader = self->block->value;
+      gtk_json_parser_start_object (self);
+      break;
+
+    case GTK_JSON_BLOCK_ARRAY:
+      gtk_json_parser_pop_block (self);
+      self->reader = self->block->value;
+      gtk_json_parser_start_array (self);
+      break;
+
+    case GTK_JSON_BLOCK_TOPLEVEL:
+      self->reader = self->start;
+      gtk_json_parser_skip_whitespace (self);
+      if (gtk_json_parser_is_eof (self))
+        {
+          gtk_json_parser_syntax_error_at (self, self->start, self->reader, "Empty document");
+        }
+      else
+        {
+          self->block->value = self->reader;
+          gtk_json_parser_parse_value (self);
+        }
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+}
+
 gsize
 gtk_json_parser_get_depth (GtkJsonParser *self)
 {
@@ -1270,7 +1301,7 @@ gtk_json_parser_get_error_location (GtkJsonParser *self,
 }
 
 static gboolean
-gtk_json_parser_has_member (GtkJsonParser *self)
+gtk_json_parser_supports_member (GtkJsonParser *self)
 {
   if (self->error)
     return FALSE;
@@ -1287,12 +1318,61 @@ gtk_json_parser_has_member (GtkJsonParser *self)
 char *
 gtk_json_parser_get_member_name (GtkJsonParser *self)
 {
-  if (!gtk_json_parser_has_member (self))
+  if (!gtk_json_parser_supports_member (self))
     return NULL;
 
   return gtk_json_unescape_string (self->block->member_name);
 }
 
+gboolean
+gtk_json_parser_has_member (GtkJsonParser *self,
+                            const char    *name)
+{
+  JsonStringIter iter;
+  gsize found, len;
+
+  if (!gtk_json_parser_supports_member (self))
+    return FALSE;
+
+  found = 0;
+
+  for (len = json_string_iter_init (&iter, self->block->member_name);
+       len > 0;
+       len = json_string_iter_next (&iter))
+    {
+      const char *s = json_string_iter_get (&iter);
+
+      if (strncmp (name + found, s, len) != 0)
+        return FALSE;
+
+      found += len;
+    }
+
+  return TRUE;
+}
+
+gboolean
+gtk_json_parser_find_member (GtkJsonParser *self,
+                             const char    *name)
+{
+  if (!gtk_json_parser_supports_member (self))
+    {
+      while (gtk_json_parser_next (self));
+      return FALSE;
+    }
+
+  gtk_json_parser_rewind (self);
+
+  do
+    {
+      if (gtk_json_parser_has_member (self, name))
+        return TRUE;
+    }
+  while (gtk_json_parser_next (self));
+
+  return FALSE;
+}
+
 gssize
 gtk_json_parser_select_member (GtkJsonParser      *self,
                                const char * const *options)
@@ -1301,7 +1381,7 @@ gtk_json_parser_select_member (GtkJsonParser      *self,
   gssize i, j;
   gsize found, len;
 
-  if (!gtk_json_parser_has_member (self))
+  if (!gtk_json_parser_supports_member (self))
     return -1;
 
   if (options[0] == NULL)
@@ -1316,15 +1396,12 @@ gtk_json_parser_select_member (GtkJsonParser      *self,
     {
       const char *s = json_string_iter_get (&iter);
 
-      if (strncmp (options[i] + found, s, len) == 0)
-        {
-          found += len;
-        }
-      else 
+      if (strncmp (options[i] + found, s, len) != 0)
         {
           for (j = i + 1; options[j]; j++)
             {
-              if (strncmp (options[j], options[i], found) == 0)
+              if (strncmp (options[j], options[i], found) == 0 &&
+                  strncmp (options[j] + found, s, len) == 0)
                 {
                   i = j;
                   break;
@@ -1333,6 +1410,7 @@ gtk_json_parser_select_member (GtkJsonParser      *self,
           if (j != i)
             return -1;
         }
+      found += len;
     }
 
   if (options[i][found] == 0)
diff --git a/gtk/json/gtkjsonparserprivate.h b/gtk/json/gtkjsonparserprivate.h
index 155a5b7603..38f508ab9f 100644
--- a/gtk/json/gtkjsonparserprivate.h
+++ b/gtk/json/gtkjsonparserprivate.h
@@ -55,9 +55,14 @@ GtkJsonParser *         gtk_json_parser_new_for_string          (const char
 void                    gtk_json_parser_free                    (GtkJsonParser          *self);
 
 gboolean                gtk_json_parser_next                    (GtkJsonParser          *self);
+void                    gtk_json_parser_rewind                  (GtkJsonParser          *self);
 gsize                   gtk_json_parser_get_depth               (GtkJsonParser          *self);
 GtkJsonNode             gtk_json_parser_get_node                (GtkJsonParser          *self);
 char *                  gtk_json_parser_get_member_name         (GtkJsonParser          *self);
+gboolean                gtk_json_parser_has_member              (GtkJsonParser          *self,
+                                                                 const char             *name);
+gboolean                gtk_json_parser_find_member             (GtkJsonParser          *self,
+                                                                 const char             *name);
 gssize                  gtk_json_parser_select_member           (GtkJsonParser          *self,
                                                                  const char * const     *options);
 


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