summaryrefslogtreecommitdiff
path: root/libappstream-glib
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2014-05-23 15:21:56 +0100
committerRichard Hughes <richard@hughsie.com>2014-05-23 15:24:40 +0100
commit517e0fb9dfd1fddd57ee62b9bb64efb0d29a0834 (patch)
treec1d9956b66054def7dff52cc0daa61a5064b2ef9 /libappstream-glib
parentec594f5ddd47b4472cb2aadcc9754552a87efc0c (diff)
downloadappstream-glib-517e0fb9dfd1fddd57ee62b9bb64efb0d29a0834.tar.gz
Add as_node_get_comment()
Comments are stored as internal attributes to avoid growing the size of AsNodeData beyond 32 bits, although there is a performance penalty for this. As comments are not often encountered in documents (and not at all in the AppStream metadata fast path) this is probably okay. By default comments are not loaded from the document, use %AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS when loading to enable this.
Diffstat (limited to 'libappstream-glib')
-rw-r--r--libappstream-glib/as-node-private.h3
-rw-r--r--libappstream-glib/as-node.c105
-rw-r--r--libappstream-glib/as-node.h3
-rw-r--r--libappstream-glib/as-self-test.c22
4 files changed, 128 insertions, 5 deletions
diff --git a/libappstream-glib/as-node-private.h b/libappstream-glib/as-node-private.h
index 354ad61..8cd742f 100644
--- a/libappstream-glib/as-node-private.h
+++ b/libappstream-glib/as-node-private.h
@@ -39,6 +39,9 @@ void as_node_set_data (GNode *node,
const gchar *cdata,
gssize cdata_len,
AsNodeInsertFlags insert_flags);
+void as_node_set_comment (GNode *node,
+ const gchar *comment,
+ gssize comment_len);
gint as_node_get_attribute_as_int (const GNode *node,
const gchar *key);
void as_node_add_attribute (GNode *node,
diff --git a/libappstream-glib/as-node.c b/libappstream-glib/as-node.c
index ebeff93..5c5cb49 100644
--- a/libappstream-glib/as-node.c
+++ b/libappstream-glib/as-node.c
@@ -278,6 +278,9 @@ as_node_get_attr_string (AsNodeData *data)
str = g_string_new ("");
for (l = data->attrs; l != NULL; l = l->next) {
attr = l->data;
+ if (g_strcmp0 (attr->key, "@comment") == 0 ||
+ g_strcmp0 (attr->key, "@comment-tmp") == 0)
+ continue;
g_string_append_printf (str, " %s=\"%s\"",
attr->key, attr->value);
}
@@ -319,9 +322,20 @@ as_node_to_xml_string (GString *xml,
AsNodeData *data = n->data;
GNode *c;
const gchar *tag_str;
+ const gchar *comment;
guint depth = g_node_depth ((GNode *) n);
gchar *attrs;
+ /* comment */
+ comment = as_node_get_comment (n);
+ if (comment != NULL) {
+ if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_INDENT) > 0)
+ as_node_add_padding (xml, depth - depth_offset);
+ g_string_append_printf (xml, "<!-- %s -->", comment);
+ if ((flags & AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE) > 0)
+ g_string_append (xml, "\n");
+ }
+
/* root node */
if (data == NULL) {
for (c = n->children; c != NULL; c = c->next)
@@ -474,6 +488,8 @@ as_node_start_element_cb (GMarkupParseContext *context,
{
AsNodeToXmlHelper *helper = (AsNodeToXmlHelper *) user_data;
AsNodeData *data;
+ GNode *current;
+ gchar *tmp;
guint i;
/* create the new node data */
@@ -486,7 +502,17 @@ as_node_start_element_cb (GMarkupParseContext *context,
}
/* add the node to the DOM */
- helper->current = g_node_append_data (helper->current, data);
+ current = g_node_append_data (helper->current, data);
+
+ /* transfer the ownership of the comment to the new child */
+ tmp = as_node_take_attribute (helper->current, "@comment-tmp");
+ if (tmp != NULL) {
+ as_node_add_attribute (current, "@comment", tmp, -1);
+ g_free (tmp);
+ }
+
+ /* the child is now the node to be processed */
+ helper->current = current;
}
/**
@@ -538,6 +564,46 @@ as_node_text_cb (GMarkupParseContext *context,
}
/**
+ * as_node_passthrough_cb:
+ **/
+static void
+as_node_passthrough_cb (GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize passthrough_len,
+ gpointer user_data,
+ GError **error)
+{
+ AsNodeToXmlHelper *helper = (AsNodeToXmlHelper *) user_data;
+ const gchar *tmp;
+ gchar *found;
+ gchar *text = NULL;
+
+ /* only keep comments when told to */
+ if ((helper->flags & AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS) == 0)
+ return;
+
+ /* xml header */
+ if (g_strstr_len (passthrough_text, passthrough_len, "<?xml") != NULL)
+ goto out;
+
+ /* get stripped comment without '<!--' and '-->' */
+ text = g_strndup (passthrough_text, passthrough_len);
+ if (!g_str_has_prefix (text, "<!--")) {
+ g_warning ("Unexpected input: %s", text);
+ goto out;
+ }
+ found = g_strrstr (text, "-->");
+ if (found != NULL)
+ *found = '\0';
+ tmp = g_strstrip (text + 4);
+ if (tmp == NULL || tmp[0] == '\0')
+ goto out;
+ as_node_add_attribute (helper->current, "@comment-tmp", tmp, -1);
+out:
+ g_free (text);
+}
+
+/**
* as_node_from_xml: (skip)
* @data: XML data
* @data_len: Length of @data, or -1 if NULL terminated
@@ -565,7 +631,7 @@ as_node_from_xml (const gchar *data,
as_node_start_element_cb,
as_node_end_element_cb,
as_node_text_cb,
- NULL,
+ as_node_passthrough_cb,
NULL };
g_return_val_if_fail (data != NULL, FALSE);
@@ -643,7 +709,7 @@ as_node_from_file (GFile *file,
as_node_start_element_cb,
as_node_end_element_cb,
as_node_text_cb,
- NULL,
+ as_node_passthrough_cb,
NULL };
/* what kind of file is this */
@@ -832,6 +898,22 @@ as_node_get_data (const GNode *node)
}
/**
+ * as_node_get_comment:
+ * @node: a #GNode
+ *
+ * Gets the node data, e.g. "Copyright 2014 Richard Hughes <richard@hughsie.com>"
+ *
+ * Return value: string value, or %NULL
+ *
+ * Since: 0.1.6
+ **/
+const gchar *
+as_node_get_comment (const GNode *node)
+{
+ return as_node_get_attribute (node, "@comment");
+}
+
+/**
* as_node_get_tag:
* @node: a #GNode
*
@@ -893,6 +975,23 @@ as_node_set_data (GNode *node,
}
/**
+ * as_node_set_comment: (skip)
+ * @node: a #GNode
+ * @comment: new comment
+ * @comment_len: length of @data, or -1 if NULL terminated
+ * @insert_flags: any %AsNodeInsertFlags.
+ *
+ * Sets new comment for the node.
+ *
+ * Since: 0.1.6
+ **/
+void
+as_node_set_comment (GNode *node, const gchar *comment, gssize comment_len)
+{
+ return as_node_add_attribute (node, "@comment", comment, comment_len);
+}
+
+/**
* as_node_take_data:
* @node: a #GNode
*
diff --git a/libappstream-glib/as-node.h b/libappstream-glib/as-node.h
index 693905d..fa45356 100644
--- a/libappstream-glib/as-node.h
+++ b/libappstream-glib/as-node.h
@@ -58,12 +58,14 @@ typedef enum {
* AsNodeFromXmlFlags:
* @AS_NODE_FROM_XML_FLAG_NONE: No extra flags to use
* @AS_NODE_FROM_XML_FLAG_LITERAL_TEXT: Treat the text as an exact string
+ * @AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS: Retain comments in the XML file
*
* The flags for converting from XML.
**/
typedef enum {
AS_NODE_FROM_XML_FLAG_NONE = 0, /* Since: 0.1.0 */
AS_NODE_FROM_XML_FLAG_LITERAL_TEXT = 1, /* Since: 0.1.3 */
+ AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS = 2, /* Since: 0.1.6 */
/*< private >*/
AS_NODE_FROM_XML_FLAG_LAST
} AsNodeFromXmlFlags;
@@ -108,6 +110,7 @@ void as_node_unref (GNode *node);
const gchar *as_node_get_name (const GNode *node);
const gchar *as_node_get_data (const GNode *node);
+const gchar *as_node_get_comment (const GNode *node);
AsTag as_node_get_tag (const GNode *node);
const gchar *as_node_get_attribute (const GNode *node,
const gchar *key);
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c
index bdeeb29..8cb5995 100644
--- a/libappstream-glib/as-self-test.c
+++ b/libappstream-glib/as-self-test.c
@@ -842,7 +842,7 @@ ch_test_node_func (void)
static void
ch_test_node_xml_func (void)
{
- const gchar *valid = "<foo><bar key=\"value\">baz</bar></foo>";
+ const gchar *valid = "<foo><!-- this documents bar --><bar key=\"value\">baz</bar></foo>";
GError *error = NULL;
GNode *n2;
GNode *root;
@@ -866,12 +866,13 @@ ch_test_node_xml_func (void)
n2 = as_node_find (root, "foo/bar");
g_assert (n2 != NULL);
g_assert_cmpstr (as_node_get_data (n2), ==, "baz");
+ g_assert_cmpstr (as_node_get_comment (n2), ==, NULL);
g_assert_cmpstr (as_node_get_attribute (n2, "key"), ==, "value");
/* convert back */
xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
g_assert (xml != NULL);
- g_assert_cmpstr (xml->str, ==, valid);
+ g_assert_cmpstr (xml->str, ==, "<foo><bar key=\"value\">baz</bar></foo>");
g_string_free (xml, TRUE);
/* with newlines */
@@ -903,6 +904,23 @@ ch_test_node_xml_func (void)
g_assert_cmpstr (xml->str, ==, "<p>One</p><p>Two</p>");
g_string_free (xml, TRUE);
as_node_unref (root);
+
+ /* keep comments */
+ root = as_node_from_xml (valid, -1,
+ AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS,
+ &error);
+ g_assert_no_error (error);
+ g_assert (root != NULL);
+ n2 = as_node_find (root, "foo/bar");
+ g_assert (n2 != NULL);
+ g_assert_cmpstr (as_node_get_comment (n2), ==, "this documents bar");
+
+ /* check comments were preserved */
+ xml = as_node_to_xml (root, AS_NODE_TO_XML_FLAG_NONE);
+ g_assert (xml != NULL);
+ g_assert_cmpstr (xml->str, ==, valid);
+ g_string_free (xml, TRUE);
+ as_node_unref (root);
}
static void