[gnome-builder/wip/slaf/xml-symbol-resolver: 11/25] xml: parser rework to use SAX and new stack
- From: Sébastien Lafargue <slafargue src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/slaf/xml-symbol-resolver: 11/25] xml: parser rework to use SAX and new stack
- Date: Wed, 8 Feb 2017 19:24:45 +0000 (UTC)
commit bc13c76d28242a415081e67803e2022dd0c2d5f3
Author: Sebastien Lafargue <slafargue gnome org>
Date: Sun Jan 29 16:13:53 2017 +0100
xml: parser rework to use SAX and new stack
plugins/xml-pack/Makefile.am | 6 +
plugins/xml-pack/ide-xml-symbol-node.c | 122 ++++++---
plugins/xml-pack/ide-xml-symbol-node.h | 15 +-
plugins/xml-pack/ide-xml-tree-builder-generic.c | 114 ++++++++
plugins/xml-pack/ide-xml-tree-builder-generic.h | 37 +++
plugins/xml-pack/ide-xml-tree-builder-ui.c | 294 ++++++++++++++++++++
plugins/xml-pack/ide-xml-tree-builder-ui.h | 37 +++
.../xml-pack/ide-xml-tree-builder-utils-private.h | 36 +++
plugins/xml-pack/ide-xml-tree-builder-utils.c | 69 +++++
plugins/xml-pack/ide-xml-tree-builder.c | 247 +----------------
10 files changed, 699 insertions(+), 278 deletions(-)
---
diff --git a/plugins/xml-pack/Makefile.am b/plugins/xml-pack/Makefile.am
index f05f02b..78e14f9 100644
--- a/plugins/xml-pack/Makefile.am
+++ b/plugins/xml-pack/Makefile.am
@@ -25,6 +25,12 @@ libxml_pack_plugin_la_SOURCES = \
ide-xml-symbol-tree.h \
ide-xml-tree-builder.c \
ide-xml-tree-builder.h \
+ ide-xml-tree-builder-generic.c \
+ ide-xml-tree-builder-generic.h \
+ ide-xml-tree-builder-ui.c \
+ ide-xml-tree-builder-ui.h \
+ ide-xml-tree-builder-utils.c \
+ ide-xml-tree-builder-utils-private.h \
ide-xml.c \
ide-xml.h \
xml-pack-plugin.c \
diff --git a/plugins/xml-pack/ide-xml-symbol-node.c b/plugins/xml-pack/ide-xml-symbol-node.c
index c1005a9..49a9305 100644
--- a/plugins/xml-pack/ide-xml-symbol-node.c
+++ b/plugins/xml-pack/ide-xml-symbol-node.c
@@ -25,38 +25,16 @@ struct _IdeXmlSymbolNode
{
IdeSymbolNode parent_instance;
GPtrArray *children;
+ gchar *element_name;
GFile *file;
- guint line;
- guint line_offset;
+ gint line;
+ gint line_offset;
gint64 serial;
};
G_DEFINE_TYPE (IdeXmlSymbolNode, ide_xml_symbol_node, IDE_TYPE_SYMBOL_NODE)
static void
-ide_xml_symbol_node_get_location_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- IdeXmlSymbolResolver *resolver = (IdeXmlSymbolResolver *)object;
- g_autoptr(IdeSourceLocation) location = NULL;
- g_autoptr(GTask) task = user_data;
- g_autoptr(GError) error = NULL;
-
- g_assert (IDE_IS_XML_SYMBOL_RESOLVER (resolver));
- g_assert (G_IS_TASK (task));
-
- //location = ide_xml_symbol_resolver_get_location_finish (resolver, result, &error);
-
- if (location == NULL)
- g_task_return_error (task, g_steal_pointer (&error));
- else
- g_task_return_pointer (task,
- g_steal_pointer (&location),
- (GDestroyNotify)ide_source_location_unref);
-}
-
-static void
ide_xml_symbol_node_get_location_async (IdeSymbolNode *node,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@@ -64,18 +42,28 @@ ide_xml_symbol_node_get_location_async (IdeSymbolNode *node,
{
IdeXmlSymbolNode *self = (IdeXmlSymbolNode *)node;
g_autoptr(GTask) task = NULL;
+ IdeContext *context;
+ IdeFile *ifile;
+ IdeSourceLocation *ret;
g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (self));
+ g_return_if_fail (G_IS_FILE (self->file));
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_xml_symbol_node_get_location_async);
- /* ide_xml_symbol_resolver_get_location_async (self->resolver, */
- /* self->index, */
- /* self->entry, */
- /* NULL, */
- /* ide_xml_symbol_node_get_location_cb, */
- /* g_steal_pointer (&task)); */
+ context = ide_object_get_context (IDE_OBJECT (self));
+ ifile = g_object_new (IDE_TYPE_FILE,
+ "file", self->file,
+ "context", context,
+ NULL);
+
+ /* TODO: libxml2 give us the end of a tag, we need to walk back
+ * in the buffer to get the start
+ */
+ ret = ide_source_location_new (ifile, self->line - 1, self->line_offset - 1, 0);
+
+ g_task_return_pointer (task, ret, (GDestroyNotify)ide_source_location_unref);
}
static IdeSourceLocation *
@@ -95,8 +83,7 @@ ide_xml_symbol_node_finalize (GObject *object)
IdeXmlSymbolNode *self = (IdeXmlSymbolNode *)object;
g_clear_pointer (&self->children, g_ptr_array_unref);
- /* self->entry = NULL; */
- /* g_clear_object (&self->index); */
+ g_free (self->element_name);
G_OBJECT_CLASS (ide_xml_symbol_node_parent_class)->finalize (object);
}
@@ -120,16 +107,17 @@ ide_xml_symbol_node_init (IdeXmlSymbolNode *self)
IdeXmlSymbolNode *
ide_xml_symbol_node_new (const gchar *name,
+ const gchar *element_name,
IdeSymbolKind kind,
GFile *file,
- guint line,
- guint line_offset)
+ gint line,
+ gint line_offset)
{
IdeXmlSymbolNode *self;
IdeSymbolFlags flags = IDE_SYMBOL_FLAGS_NONE;
g_assert (!ide_str_empty0 (name));
- //g_assert (G_IS_FILE (file));
+ g_assert (G_IS_FILE (file)|| file == NULL);
self = g_object_new (IDE_TYPE_XML_SYMBOL_NODE,
"name", name,
@@ -137,7 +125,14 @@ ide_xml_symbol_node_new (const gchar *name,
"flags", flags,
NULL);
- self->file = file;
+ if (ide_str_empty0 (element_name))
+ self->element_name = g_strdup ("unknow");
+ else
+ self->element_name = g_strdup (element_name);
+
+ if (file != NULL)
+ self->file = g_object_ref (file);
+
self->line = line;
self->line_offset = line_offset;
@@ -173,6 +168,7 @@ ide_xml_symbol_node_take_child (IdeXmlSymbolNode *self,
if (self->children == NULL)
self->children = g_ptr_array_new_with_free_func (g_object_unref);
+
g_ptr_array_add (self->children, child);
}
@@ -183,3 +179,55 @@ ide_xml_symbol_node_get_serial (IdeXmlSymbolNode *self)
return self->serial;
}
+
+void
+ide_xml_symbol_node_set_location (IdeXmlSymbolNode *self,
+ GFile *file,
+ gint line,
+ gint line_offset)
+{
+ g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (self));
+ g_return_if_fail (G_IS_FILE (file) || file == NULL);
+
+ g_clear_object (&self->file);
+ if (file != NULL)
+ self->file = g_object_ref (file);
+
+ self->line = line;
+ self->line_offset = line_offset;
+}
+
+GFile *
+ide_xml_symbol_node_get_location (IdeXmlSymbolNode *self,
+ gint *line,
+ gint *line_offset)
+{
+ g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), NULL);
+
+ if (line != NULL)
+ *line = self->line;
+
+ if (line_offset != NULL)
+ *line_offset = self->line_offset;
+
+ return self->file;
+}
+
+const gchar *
+ide_xml_symbol_node_get_element_name (IdeXmlSymbolNode *self)
+{
+ g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), NULL);
+
+ return self->element_name;
+}
+
+void
+ide_xml_symbol_node_set_element_name (IdeXmlSymbolNode *self,
+ const gchar *element_name)
+{
+ g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (self));
+ g_return_if_fail (!ide_str_empty0 (element_name));
+
+ g_free (self->element_name);
+ self->element_name = g_strdup (element_name);
+}
diff --git a/plugins/xml-pack/ide-xml-symbol-node.h b/plugins/xml-pack/ide-xml-symbol-node.h
index 613beba..82bda7f 100644
--- a/plugins/xml-pack/ide-xml-symbol-node.h
+++ b/plugins/xml-pack/ide-xml-symbol-node.h
@@ -30,16 +30,27 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdeXmlSymbolNode, ide_xml_symbol_node, IDE, XML_SYMBOL_NODE, IdeSymbolNode)
IdeXmlSymbolNode *ide_xml_symbol_node_new (const gchar *name,
+ const gchar *element_name,
IdeSymbolKind kind,
GFile *file,
- guint line,
- guint line_offset);
+ gint line,
+ gint line_offset);
void ide_xml_symbol_node_take_child (IdeXmlSymbolNode *self,
IdeXmlSymbolNode *child);
+const gchar *ide_xml_symbol_node_get_element_name (IdeXmlSymbolNode *self);
+GFile * ide_xml_symbol_node_get_location (IdeXmlSymbolNode *self,
+ gint *line,
+ gint *line_offset);
guint ide_xml_symbol_node_get_n_children (IdeXmlSymbolNode *self);
IdeSymbolNode *ide_xml_symbol_node_get_nth_child (IdeXmlSymbolNode *self,
guint nth_child);
gint64 ide_xml_symbol_node_get_serial (IdeXmlSymbolNode *self);
+void ide_xml_symbol_node_set_location (IdeXmlSymbolNode *self,
+ GFile *file,
+ gint line,
+ gint line_offset);
+void ide_xml_symbol_node_set_element_name (IdeXmlSymbolNode *self,
+ const gchar *element_name);
G_END_DECLS
diff --git a/plugins/xml-pack/ide-xml-tree-builder-generic.c b/plugins/xml-pack/ide-xml-tree-builder-generic.c
new file mode 100644
index 0000000..11376ce
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-tree-builder-generic.c
@@ -0,0 +1,114 @@
+/* ide-xml-tree-builder-generic.c
+ *
+ * Copyright (C) 2017 Sebastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ide-xml-stack.h"
+#include "ide-xml-tree-builder-utils-private.h"
+
+#include "ide-xml-tree-builder-generic.h"
+
+static IdeXmlSymbolNode *
+create_node_from_reader (XmlReader *reader)
+{
+ const gchar *name;
+ GFile *file = NULL;
+ guint line = 0;
+ guint line_offset = 0;
+
+ name = xml_reader_get_name (reader);
+
+ return ide_xml_symbol_node_new (name, NULL,
+ IDE_SYMBOL_UI_OBJECT,
+ file, line, line_offset);
+}
+
+IdeXmlSymbolNode *
+ide_xml_tree_builder_generic_create (IdeXmlSax *parser,
+ GFile *file,
+ const gchar *data,
+ gsize size)
+{
+ IdeXmlStack *stack;
+ IdeXmlSymbolNode *root_node;
+ IdeXmlSymbolNode *parent_node;
+ IdeXmlSymbolNode *current_node;
+ IdeXmlSymbolNode *previous_node = NULL;
+ xmlReaderTypes type;
+ gint depth = 0;
+ gint current_depth = 0;
+ gboolean is_empty;
+
+ /* g_assert (XML_IS_READER (reader)); */
+
+ /* stack = stack_new (); */
+
+ /* parent_node = root_node = ide_xml_symbol_node_new ("root", IDE_SYMBOL_NONE, */
+ /* NULL, 0, 0); */
+ /* stack_push (stack, parent_node); */
+
+ /* while (xml_reader_read (reader)) */
+ /* { */
+ /* type = xml_reader_get_node_type (reader); */
+ /* if ( type == XML_READER_TYPE_ELEMENT) */
+ /* { */
+ /* current_node = create_node_from_reader (reader); */
+ /* depth = xml_reader_get_depth (reader); */
+ /* is_empty = xml_reader_is_empty_element (reader); */
+ /* if (depth < 0) */
+ /* { */
+ /* g_warning ("Wrong xml element depth, current:%i new:%i\n", current_depth, depth); */
+ /* break; */
+ /* } */
+
+ /* if (depth > current_depth) */
+ /* { */
+ /* ++current_depth; */
+ /* stack_push (stack, parent_node); */
+
+ /* g_assert (previous_node != NULL); */
+ /* parent_node = previous_node; */
+ /* ide_xml_symbol_node_take_child (parent_node, current_node); */
+ /* } */
+ /* else if (depth < current_depth) */
+ /* { */
+ /* --current_depth; */
+ /* parent_node = stack_pop (stack); */
+ /* if (parent_node == NULL) */
+ /* { */
+ /* g_warning ("Xml nodes stack empty\n"); */
+ /* break; */
+ /* } */
+
+ /* g_assert (parent_node != NULL); */
+ /* ide_xml_symbol_node_take_child (parent_node, current_node); */
+ /* } */
+ /* else */
+ /* { */
+ /* ide_xml_symbol_node_take_child (parent_node, current_node); */
+ /* } */
+
+ /* previous_node = current_node; */
+ /* print_node (current_node, depth); */
+ /* } */
+ /* } */
+
+ /* printf ("stack size:%li\n", stack_get_size (stack)); */
+
+ /* stack_destroy (stack); */
+
+ return root_node;
+}
diff --git a/plugins/xml-pack/ide-xml-tree-builder-generic.h b/plugins/xml-pack/ide-xml-tree-builder-generic.h
new file mode 100644
index 0000000..b490fb4
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-tree-builder-generic.h
@@ -0,0 +1,37 @@
+/* ide-xml-tree-builder-generic.h
+ *
+ * Copyright (C) 2017 Sebastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_XML_TREE_BUILDER_GENERIC_H
+#define IDE_XML_TREE_BUILDER_GENERIC_H
+
+#include <glib.h>
+
+#include "ide-xml-sax.h"
+#include "ide-xml-symbol-node.h"
+#include "xml-reader.h"
+
+G_BEGIN_DECLS
+
+IdeXmlSymbolNode *ide_xml_tree_builder_generic_create (IdeXmlSax *parser,
+ GFile *file,
+ const gchar *data,
+ gsize size);
+
+G_END_DECLS
+
+#endif /* IDE_XML_TREE_BUILDER_GENERIC_H */
diff --git a/plugins/xml-pack/ide-xml-tree-builder-ui.c b/plugins/xml-pack/ide-xml-tree-builder-ui.c
new file mode 100644
index 0000000..a81f29d
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-tree-builder-ui.c
@@ -0,0 +1,294 @@
+/* ide-xml-tree-builder-ui.c
+ *
+ * Copyright (C) 2017 Sebastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ide-xml-stack.h"
+#include "ide-xml-symbol-node.h"
+#include "ide-xml-tree-builder-utils-private.h"
+
+#include "ide-xml-tree-builder-ui.h"
+
+typedef struct _ParserState
+{
+ IdeXmlSax *parser;
+ IdeXmlStack *stack;
+ GFile *file;
+ IdeXmlSymbolNode *root_node;
+ IdeXmlSymbolNode *parent_node;
+ IdeXmlSymbolNode *current_node;
+ gint current_depth;
+} ParserState;
+
+static void
+parser_state_free (ParserState *state)
+{
+ g_clear_object (&state->stack);
+ g_clear_object (&state->file);
+ g_clear_object (&state->parser);
+}
+
+static void
+state_processing (ParserState *state,
+ const gchar *element_name,
+ IdeXmlSymbolNode *node,
+ IdeXmlSaxCallbackType callback_type)
+{
+ IdeXmlSymbolNode *parent_node;
+ IdeXmlSymbolNode *popped_node;
+ g_autofree gchar *popped_element_name = NULL;
+ gint line;
+ gint line_offset;
+ gint depth;
+
+ depth = ide_xml_sax_get_depth (state->parser);
+ printf ("[name:%s depth:%i] ", element_name, depth);
+
+ if (node == NULL)
+ {
+ if (callback_type == IDE_XML_SAX_CALLBACK_TYPE_START_ELEMENT)
+ {
+ ide_xml_stack_push (state->stack, element_name, NULL, state->parent_node, depth);
+
+ printf ("no node PUSH %i->%i\n", state->current_depth, depth);
+ }
+ else if (callback_type == IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT)
+ {
+ /* TODO: compare current with popped */
+ if (ide_xml_stack_is_empty (state->stack))
+ {
+ g_warning ("Xml nodes stack empty\n");
+ return;
+ }
+
+ popped_node = ide_xml_stack_pop (state->stack, &popped_element_name, &parent_node, &depth);
+ state->parent_node = parent_node;
+ g_assert (state->parent_node != NULL);
+
+ printf ("no node POP %i->%i name:%s parent:%p\n",
+ state->current_depth, depth, popped_element_name, state->parent_node);
+ }
+
+ state->current_depth = depth;
+ state->current_node = NULL;
+ return;
+ }
+
+ ide_xml_sax_get_position (state->parser, &line, &line_offset);
+ ide_xml_symbol_node_set_location (node, g_object_ref (state->file), line, line_offset);
+
+ /* TODO: take end elements into account and use:
+ * || ABS (depth - current_depth) > 1
+ */
+ if (depth < 0)
+ {
+ g_warning ("Wrong xml element depth, current:%i new:%i\n", state->current_depth, depth);
+ return;
+ }
+
+ if (callback_type == IDE_XML_SAX_CALLBACK_TYPE_START_ELEMENT)
+ {
+ ide_xml_stack_push (state->stack, element_name, node, state->parent_node, depth);
+ ide_xml_symbol_node_take_child (state->parent_node, node);
+
+ printf ("PUSH %i->%i current:%p parent:%p\n",
+ state->current_depth, depth, node, state->parent_node);
+
+ state->parent_node = node;
+ }
+ else if (callback_type == IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT)
+ {
+ /* TODO: compare current with popped */
+ if (ide_xml_stack_is_empty (state->stack))
+ {
+ g_warning ("Xml nodes stack empty\n");
+ return;
+ }
+
+ popped_node = ide_xml_stack_pop (state->stack, &popped_element_name, &parent_node, &depth);
+ state->parent_node = parent_node;
+ g_assert (state->parent_node != NULL);
+
+ printf ("POP %i->%i name:%s parent node:%p\n",
+ state->current_depth, depth, popped_element_name, parent_node);
+ }
+ else
+ {
+ printf ("---- %i->%i\n", state->current_depth, depth);
+ ide_xml_symbol_node_take_child (state->parent_node, node);
+ }
+
+ state->current_depth = depth;
+ state->current_node = node;
+ print_node (node, depth);
+}
+
+static const gchar *
+get_attribute (const guchar **list,
+ const gchar *name,
+ const gchar *replacement)
+{
+ const gchar *value = NULL;
+
+ value = list_get_attribute (list, name);
+ return ide_str_empty0 (value) ? ((replacement != NULL) ? replacement : NULL) : value;
+}
+
+static void
+start_element_sax_cb (ParserState *state,
+ const xmlChar *name,
+ const xmlChar **atttributes)
+{
+ g_autoptr (GString) string = NULL;
+ const gchar *value = NULL;
+ IdeXmlSymbolNode *node = NULL;
+
+ string = g_string_new (NULL);
+
+ if (ide_str_equal0 (name, "child"))
+ {
+ g_string_append (string, "child");
+
+ if (NULL != (value = get_attribute (atttributes, "type", NULL)))
+ {
+ g_string_append (string, " type: ");
+ g_string_append (string, value);
+ }
+
+ if (NULL != (value = get_attribute (atttributes, "internal-child", NULL)))
+ {
+ g_string_append (string, " internal: ");
+ g_string_append (string, value);
+ }
+
+ node = ide_xml_symbol_node_new (string->str, "child",
+ IDE_SYMBOL_UI_CHILD, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "object"))
+ {
+ value = get_attribute (atttributes, "class", "?");
+ g_string_append (string, value);
+
+ if (NULL != (value = list_get_attribute (atttributes, "id")))
+ {
+ g_string_append (string, " id: ");
+ g_string_append (string, value);
+ }
+
+ node = ide_xml_symbol_node_new (string->str, "object",
+ IDE_SYMBOL_UI_OBJECT, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "template"))
+ {
+ value = get_attribute (atttributes, "class", "?");
+ g_string_append (string, value);
+
+ value = get_attribute (atttributes, "parent", "?");
+ g_string_append (string, " parent: ");
+ g_string_append (string, value);
+
+ node = ide_xml_symbol_node_new (string->str, (const gchar *)name,
+ IDE_SYMBOL_UI_TEMPLATE, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "packing"))
+ {
+ node = ide_xml_symbol_node_new ("packing", "packing",
+ IDE_SYMBOL_UI_PACKING, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "style"))
+ {
+ /* TODO: collect style classes names */
+ node = ide_xml_symbol_node_new ("style", "style",
+ IDE_SYMBOL_UI_STYLE, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "menu"))
+ {
+ value = get_attribute (atttributes, "id", "?");
+ g_string_append (string, value);
+
+ node = ide_xml_symbol_node_new (string->str, "menu",
+ IDE_SYMBOL_UI_MENU, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "submenu"))
+ {
+ /* TODO: show content of attribute name="label" */
+ value = get_attribute (atttributes, "id", "?");
+ g_string_append (string, value);
+
+ node = ide_xml_symbol_node_new (string->str, "submenu",
+ IDE_SYMBOL_UI_SUBMENU, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "section"))
+ {
+ value = get_attribute (atttributes, "id", "?");
+ g_string_append (string, value);
+
+ node = ide_xml_symbol_node_new (string->str, "section",
+ IDE_SYMBOL_UI_SECTION, NULL, 0, 0);
+ }
+ else if (ide_str_equal0 (name, "item"))
+ {
+ /* TODO: show content of attribute name="label" */
+ node = ide_xml_symbol_node_new ("item", "item",
+ IDE_SYMBOL_UI_ITEM, NULL, 0, 0);
+ }
+
+ state_processing (state, (const gchar *)name, node, IDE_XML_SAX_CALLBACK_TYPE_START_ELEMENT);
+}
+
+static void
+end_element_sax_cb (ParserState *state,
+ const xmlChar *name)
+{
+ printf ("end element:%s\n", name);
+
+ state_processing (state, (const gchar *)name, NULL, IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT);
+}
+
+IdeXmlSymbolNode *
+ide_xml_tree_builder_ui_create (IdeXmlSax *parser,
+ GFile *file,
+ const gchar *data,
+ gsize length)
+{
+ ParserState *state;
+ g_autofree gchar *uri = NULL;
+
+ g_assert (IDE_IS_XML_SAX (parser));
+
+ state = g_slice_new0 (ParserState);
+ state->parser = g_object_ref (parser);
+ state->stack = ide_xml_stack_new ();
+ state->file = g_object_ref (file);
+
+ ide_xml_sax_clear (parser);
+ ide_xml_sax_set_callback (parser, IDE_XML_SAX_CALLBACK_TYPE_START_ELEMENT, start_element_sax_cb);
+ ide_xml_sax_set_callback (parser, IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT, end_element_sax_cb);
+
+ state->root_node = ide_xml_symbol_node_new ("root", "root", IDE_SYMBOL_NONE, NULL, 0, 0);
+ ide_xml_stack_push (state->stack, "root", state->root_node, NULL, 0);
+
+ state->parent_node = state->root_node;
+ printf ("root node:%p\n", state->root_node);
+
+ uri = g_file_get_uri (file);
+ ide_xml_sax_parse (parser, data, length, uri, state);
+ printf ("stack size:%li\n", ide_xml_stack_get_size (state->stack));
+
+ parser_state_free (state);
+
+ return state->root_node;
+}
diff --git a/plugins/xml-pack/ide-xml-tree-builder-ui.h b/plugins/xml-pack/ide-xml-tree-builder-ui.h
new file mode 100644
index 0000000..6d6ae51
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-tree-builder-ui.h
@@ -0,0 +1,37 @@
+/* ide-xml-tree-builder-ui.h
+ *
+ * Copyright (C) 2017 Sebastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_XML_TREE_BUILDER_UI_H
+#define IDE_XML_TREE_BUILDER_UI_H
+
+#include <glib.h>
+
+#include "ide-xml-sax.h"
+#include "ide-xml-symbol-node.h"
+#include "xml-reader.h"
+
+G_BEGIN_DECLS
+
+IdeXmlSymbolNode *ide_xml_tree_builder_ui_create (IdeXmlSax *parser,
+ GFile *file,
+ const gchar *data,
+ gsize length);
+
+G_END_DECLS
+
+#endif /* IDE_XML_TREE_BUILDER_UI_H */
diff --git a/plugins/xml-pack/ide-xml-tree-builder-utils-private.h
b/plugins/xml-pack/ide-xml-tree-builder-utils-private.h
new file mode 100644
index 0000000..038f5a5
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-tree-builder-utils-private.h
@@ -0,0 +1,36 @@
+/* ide-xml-tree-builder-utils-private.h
+ *
+ * Copyright (C) 2017 Sebastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef IDE_XML_TREE_BUILDER_UTILS_PRIVATE_H
+#define IDE_XML_TREE_BUILDER_UTILS_PRIVATE_H
+
+#include <glib.h>
+#include <ide.h>
+
+#include "ide-xml-symbol-node.h"
+
+G_BEGIN_DECLS
+
+const gchar *list_get_attribute (const guchar **attributes,
+ const gchar *name);
+void print_node (IdeXmlSymbolNode *node,
+ guint depth);
+
+G_END_DECLS
+
+#endif /* IDE_XML_TREE_BUILDER_UTILS_PRIVATE_H */
+
diff --git a/plugins/xml-pack/ide-xml-tree-builder-utils.c b/plugins/xml-pack/ide-xml-tree-builder-utils.c
new file mode 100644
index 0000000..6298045
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-tree-builder-utils.c
@@ -0,0 +1,69 @@
+/* ide-xml-tree-builder-utils.c
+ *
+ * Copyright (C) 2017 Sebastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ide-xml-tree-builder-utils-private.h"
+
+void
+print_node (IdeXmlSymbolNode *node,
+ guint depth)
+{
+ g_autofree gchar *spacer;
+ gint line;
+ gint line_offset;
+
+ g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (node) || node == NULL);
+
+ if (node == NULL)
+ {
+ g_warning ("Node NULL");
+ return;
+ }
+
+ spacer = g_strnfill (depth, '\t');
+ ide_xml_symbol_node_get_location (node, &line, &line_offset);
+
+ printf ("%s%s (%i) at (%i,%i) %p\n",
+ spacer,
+ ide_symbol_node_get_name (IDE_SYMBOL_NODE (node)),
+ depth,
+ line,
+ line_offset,
+ node);
+}
+
+const gchar *
+list_get_attribute (const guchar **attributes,
+ const gchar *name)
+{
+ const guchar **l = attributes;
+
+ g_return_val_if_fail (!ide_str_empty0 (name), NULL);
+
+ if (attributes == NULL)
+ return NULL;
+
+ while (l [0] != NULL)
+ {
+ if (ide_str_equal0 (name, l [0]))
+ return (const gchar *)l [1];
+
+ l += 2;
+ }
+
+ return NULL;
+}
diff --git a/plugins/xml-pack/ide-xml-tree-builder.c b/plugins/xml-pack/ide-xml-tree-builder.c
index d290de6..cb580f6 100644
--- a/plugins/xml-pack/ide-xml-tree-builder.c
+++ b/plugins/xml-pack/ide-xml-tree-builder.c
@@ -20,64 +20,19 @@
#include <glib/gi18n.h>
#include "xml-reader.h"
+#include "ide-xml-sax.h"
+#include "ide-xml-tree-builder-generic.h"
+#include "ide-xml-tree-builder-ui.h"
#include "ide-xml-tree-builder.h"
-typedef GPtrArray IdeXmlStack;
-
-static inline IdeXmlStack *
-stack_new (void)
-{
- return g_ptr_array_new ();
-}
-
-static inline void
-stack_push (IdeXmlStack *stack,
- gpointer ptr)
-{
- g_ptr_array_add (stack, ptr);
-}
-
-static inline gpointer
-stack_pop (IdeXmlStack *stack)
-{
- gint end = stack->len - 1;
-
- return (end < 0) ? NULL : g_ptr_array_remove_index_fast (stack, end);
-}
-
-static inline gint
-stack_is_empty (IdeXmlStack *stack)
-{
- return (stack->len == 0);
-}
-
-static inline void
-stack_destroy (IdeXmlStack *stack)
-{
- g_ptr_array_unref (stack);
-}
-
-static inline gsize
-stack_get_size (IdeXmlStack *stack)
-{
- return stack->len;
-}
-
-struct _IdeXmlService
-{
- IdeObject parent_instance;
-
- EggTaskCache *trees;
- GCancellable *cancellable;
-};
struct _IdeXmlTreeBuilder
{
IdeObject parent_instance;
};
typedef struct{
- XmlReader *reader;
+ IdeXmlSax *parser;
GBytes *content;
GFile *file;
} BuilderState;
@@ -85,198 +40,13 @@ typedef struct{
static void
builder_state_free (BuilderState *state)
{
- g_clear_object (&state->reader);
+ g_clear_object (&state->parser);
g_clear_pointer (&state->content, g_bytes_unref);
g_clear_object (&state->file);
}
G_DEFINE_TYPE (IdeXmlTreeBuilder, ide_xml_tree_builder, IDE_TYPE_OBJECT)
-static IdeXmlSymbolNode *
-create_node_from_reader (XmlReader *reader)
-{
- const gchar *name;
- GFile *file = NULL;
- guint line = 0;
- guint line_offset = 0;
-
- name = xml_reader_get_name (reader);
-
- return ide_xml_symbol_node_new (name, IDE_SYMBOL_UI_OBJECT,
- file, line, line_offset);
-}
-
-static void
-print_node (IdeXmlSymbolNode *node,
- guint depth)
-{
- g_autofree gchar *spacer;
-
- spacer = g_strnfill (depth, '\t');
- printf ("%s%s (%i)\n",
- spacer,
- ide_symbol_node_get_name (IDE_SYMBOL_NODE (node)),
- depth);
-}
-
-static IdeXmlSymbolNode *
-ide_xml_service_walk_tree_ui (IdeXmlTreeBuilder *self,
- XmlReader *reader)
-{
- IdeXmlStack *stack;
- IdeXmlSymbolNode *root_node;
- IdeXmlSymbolNode *parent_node;
- IdeXmlSymbolNode *current_node;
- IdeXmlSymbolNode *previous_node = NULL;
- xmlReaderTypes type;
- gint depth = 0;
- gint current_depth = 0;
- gboolean is_empty;
-
- g_assert (IDE_IS_XML_TREE_BUILDER (self));
- g_assert (XML_IS_READER (reader));
-
- stack = stack_new ();
-
- parent_node = root_node = ide_xml_symbol_node_new ("root", IDE_SYMBOL_NONE,
- NULL, 0, 0);
- stack_push (stack, parent_node);
-
- while (xml_reader_read (reader))
- {
- type = xml_reader_get_node_type (reader);
- if ( type == XML_READER_TYPE_ELEMENT)
- {
- current_node = create_node_from_reader (reader);
- depth = xml_reader_get_depth (reader);
- is_empty = xml_reader_is_empty_element (reader);
-
- /* TODO: take end elements into account and use:
- * || ABS (depth - current_depth) > 1
- */
- if (depth < 0)
- {
- g_warning ("Wrong xml element depth, current:%i new:%i\n", current_depth, depth);
- break;
- }
-
- if (depth > current_depth)
- {
- ++current_depth;
- stack_push (stack, parent_node);
-
- g_assert (previous_node != NULL);
- parent_node = previous_node;
- ide_xml_symbol_node_take_child (parent_node, current_node);
- }
- else if (depth < current_depth)
- {
- --current_depth;
- parent_node = stack_pop (stack);
- if (parent_node == NULL)
- {
- g_warning ("Xml nodes stack empty\n");
- break;
- }
-
- g_assert (parent_node != NULL);
- ide_xml_symbol_node_take_child (parent_node, current_node);
- }
- else
- {
- ide_xml_symbol_node_take_child (parent_node, current_node);
- }
-
- previous_node = current_node;
- print_node (current_node, depth);
- }
- }
-
- stack_destroy (stack);
-
- return root_node;
-}
-
-static IdeXmlSymbolNode *
-ide_xml_service_walk_tree_xml (IdeXmlTreeBuilder *self,
- XmlReader *reader)
-{
- IdeXmlStack *stack;
- IdeXmlSymbolNode *root_node;
- IdeXmlSymbolNode *parent_node;
- IdeXmlSymbolNode *current_node;
- IdeXmlSymbolNode *previous_node = NULL;
- xmlReaderTypes type;
- gint depth = 0;
- gint current_depth = 0;
- gboolean is_empty;
-
- g_assert (IDE_IS_XML_TREE_BUILDER (self));
- g_assert (XML_IS_READER (reader));
-
- stack = stack_new ();
-
- parent_node = root_node = ide_xml_symbol_node_new ("root", IDE_SYMBOL_NONE,
- NULL, 0, 0);
- stack_push (stack, parent_node);
-
- while (xml_reader_read (reader))
- {
- type = xml_reader_get_node_type (reader);
- if ( type == XML_READER_TYPE_ELEMENT)
- {
- current_node = create_node_from_reader (reader);
- depth = xml_reader_get_depth (reader);
- is_empty = xml_reader_is_empty_element (reader);
-
- /* TODO: take end elements into account and use:
- * || ABS (depth - current_depth) > 1
- */
- if (depth < 0)
- {
- g_warning ("Wrong xml element depth, current:%i new:%i\n", current_depth, depth);
- break;
- }
-
- if (depth > current_depth)
- {
- ++current_depth;
- stack_push (stack, parent_node);
-
- g_assert (previous_node != NULL);
- parent_node = previous_node;
- ide_xml_symbol_node_take_child (parent_node, current_node);
- }
- else if (depth < current_depth)
- {
- --current_depth;
- parent_node = stack_pop (stack);
- if (parent_node == NULL)
- {
- g_warning ("Xml nodes stack empty\n");
- break;
- }
-
- g_assert (parent_node != NULL);
- ide_xml_symbol_node_take_child (parent_node, current_node);
- }
- else
- {
- ide_xml_symbol_node_take_child (parent_node, current_node);
- }
-
- previous_node = current_node;
- print_node (current_node, depth);
- }
- }
-
- printf ("stack size:%li\n", stack_get_size (stack));
-
- stack_destroy (stack);
-
- return root_node;
-}
-
static GBytes *
ide_xml_service_get_file_content (IdeXmlTreeBuilder *self,
GFile *file)
@@ -356,12 +126,11 @@ build_tree_worker (GTask *task,
data = g_bytes_get_data (state->content, &size);
uri = g_file_get_uri (state->file);
- xml_reader_load_from_data (state->reader, data, size, uri, NULL);
if (ide_xml_tree_builder_file_is_ui (state->file,data, size))
- root_node = ide_xml_service_walk_tree_ui (self, state->reader);
+ root_node = ide_xml_tree_builder_ui_create (state->parser, state->file, data, size);
else
- root_node = ide_xml_service_walk_tree_xml (self, state->reader);
+ root_node = ide_xml_tree_builder_generic_create (state->parser, state->file, data, size);
if (root_node == NULL)
{
@@ -403,7 +172,7 @@ ide_xml_tree_builder_build_tree_async (IdeXmlTreeBuilder *self,
}
state = g_slice_new0 (BuilderState);
- state->reader = xml_reader_new ();
+ state->parser = ide_xml_sax_new ();
state->content = g_bytes_ref (content);
state->file = g_object_ref (file);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]