Refactor XBEL writing to use GString and filter out control characters
The writing becomes faster because we avoid some redundant allocations and we improve XML compatibility by filtering out control characters which are not supported in Midori.
This commit is contained in:
parent
36a5ef50b7
commit
da0304964e
1 changed files with 115 additions and 84 deletions
|
@ -454,74 +454,114 @@ midori_array_from_file (KatzeArray* array,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static gchar*
|
/* Inspired by append_escaped_text() from gmarkup.c in Glib.
|
||||||
_simple_xml_element (const gchar* name,
|
The main difference is that we filter out control characters. */
|
||||||
const gchar* value)
|
static void
|
||||||
|
string_append_escaped (GString *str,
|
||||||
|
const gchar *text)
|
||||||
{
|
{
|
||||||
gchar* value_escaped;
|
gssize length;
|
||||||
gchar* markup;
|
const gchar* p;
|
||||||
|
const gchar* end;
|
||||||
|
gunichar c;
|
||||||
|
|
||||||
if (!value)
|
length = strlen (text);
|
||||||
return g_strdup ("");
|
p = text;
|
||||||
value_escaped = g_markup_escape_text (value, -1);
|
end = text + length;
|
||||||
markup = g_strdup_printf ("<%s>%s</%s>\n", name, value_escaped, name);
|
|
||||||
g_free (value_escaped);
|
while (p != end)
|
||||||
return markup;
|
{
|
||||||
|
const gchar *next;
|
||||||
|
next = g_utf8_next_char (p);
|
||||||
|
|
||||||
|
switch (*p)
|
||||||
|
{
|
||||||
|
case '&':
|
||||||
|
g_string_append (str, "&");
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
g_string_append (str, "<");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
g_string_append (str, ">");
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
g_string_append (str, "'");
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
g_string_append (str, """);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c = g_utf8_get_char (p);
|
||||||
|
if (g_unichar_iscntrl (c))
|
||||||
|
g_string_append_c (str, ' ');
|
||||||
|
else if ((0x1 <= c && c <= 0x8)
|
||||||
|
|| (0xb <= c && c <= 0xc)
|
||||||
|
|| (0xe <= c && c <= 0x1f)
|
||||||
|
|| (0x7f <= c && c <= 0x84)
|
||||||
|
|| (0x86 <= c && c <= 0x9f))
|
||||||
|
g_string_append_printf (str, "&#x%x;", c);
|
||||||
|
else
|
||||||
|
g_string_append_len (str, p, next - p);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar*
|
p = next;
|
||||||
katze_item_to_data (KatzeItem* item)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
string_append_xml_element (GString* string,
|
||||||
|
const gchar* name,
|
||||||
|
const gchar* value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
g_string_append_printf (string, "<%s>", name);
|
||||||
|
string_append_escaped (string, value);
|
||||||
|
g_string_append_printf (string, "</%s>\n", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
string_append_item (GString* string,
|
||||||
|
KatzeItem* item)
|
||||||
{
|
{
|
||||||
gchar* markup;
|
gchar* markup;
|
||||||
gchar* metadata;
|
gchar* metadata;
|
||||||
|
|
||||||
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
|
||||||
markup = NULL;
|
markup = NULL;
|
||||||
metadata = katze_item_metadata_to_xbel (item);
|
metadata = katze_item_metadata_to_xbel (item);
|
||||||
if (KATZE_IS_ARRAY (item))
|
if (KATZE_IS_ARRAY (item))
|
||||||
{
|
{
|
||||||
GString* _markup = g_string_new (NULL);
|
|
||||||
guint i = 0;
|
guint i = 0;
|
||||||
KatzeItem* _item;
|
KatzeItem* _item;
|
||||||
while ((_item = katze_array_get_nth_item (KATZE_ARRAY (item), i++)))
|
KatzeArray* array = KATZE_ARRAY (item);
|
||||||
{
|
|
||||||
gchar* item_markup = katze_item_to_data (_item);
|
g_string_append (string, "<folder>\n");
|
||||||
g_string_append (_markup, item_markup);
|
/* FIXME: " folded=\"no\" */
|
||||||
g_free (item_markup);
|
string_append_xml_element (string, "title", katze_item_get_name (item));
|
||||||
}
|
string_append_xml_element (string, "desc", katze_item_get_text (item));
|
||||||
/* gchar* folded = item->folded ? NULL : g_strdup_printf (" folded=\"no\""); */
|
while ((_item = katze_array_get_nth_item (array, i++)))
|
||||||
gchar* title = _simple_xml_element ("title", katze_item_get_name (item));
|
string_append_item (string, _item);
|
||||||
gchar* desc = _simple_xml_element ("desc", katze_item_get_text (item));
|
g_string_append (string, metadata);
|
||||||
markup = g_strdup_printf ("<folder%s>\n%s%s%s%s</folder>\n",
|
g_string_append (string, "</folder>\n");
|
||||||
"" /* folded ? folded : "" */,
|
|
||||||
title, desc,
|
|
||||||
_markup->str,
|
|
||||||
metadata);
|
|
||||||
g_string_free (_markup, TRUE);
|
|
||||||
/* g_free (folded); */
|
|
||||||
g_free (title);
|
|
||||||
g_free (desc);
|
|
||||||
}
|
}
|
||||||
else if (katze_item_get_uri (item))
|
else if (katze_item_get_uri (item))
|
||||||
{
|
{
|
||||||
gchar* href_escaped = g_markup_escape_text (katze_item_get_uri (item), -1);
|
g_string_append (string, "<bookmark href=\"");
|
||||||
gchar* href = g_strdup_printf (" href=\"%s\"", href_escaped);
|
string_append_escaped (string, katze_item_get_uri (item));
|
||||||
g_free (href_escaped);
|
g_string_append (string, "\">\n");
|
||||||
gchar* title = _simple_xml_element ("title", katze_item_get_name (item));
|
string_append_xml_element (string, "title", katze_item_get_name (item));
|
||||||
gchar* desc = _simple_xml_element ("desc", katze_item_get_text (item));
|
string_append_xml_element (string, "desc", katze_item_get_text (item));
|
||||||
markup = g_strdup_printf ("<bookmark%s>\n%s%s%s</bookmark>\n",
|
g_string_append (string, metadata);
|
||||||
href,
|
g_string_append (string, "</bookmark>\n");
|
||||||
title, desc,
|
|
||||||
metadata);
|
|
||||||
g_free (href);
|
|
||||||
g_free (title);
|
|
||||||
g_free (desc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
markup = g_strdup ("<separator/>\n");
|
g_string_append (string, "<separator/>\n");
|
||||||
g_free (metadata);
|
g_free (metadata);
|
||||||
return markup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar*
|
static gchar*
|
||||||
|
@ -547,18 +587,26 @@ katze_item_metadata_to_xbel (KatzeItem* item)
|
||||||
while ((key = g_list_nth_data (keys, i++)))
|
while ((key = g_list_nth_data (keys, i++)))
|
||||||
if ((value = katze_item_get_meta_string (item, key)))
|
if ((value = katze_item_get_meta_string (item, key)))
|
||||||
{
|
{
|
||||||
gchar* escaped = g_markup_escape_text (value, -1);
|
|
||||||
namespace = strchr (key, ':');
|
namespace = strchr (key, ':');
|
||||||
if (key[0] == ':') /* MicroB uses un-namespaced children */
|
if (key[0] == ':') /* MicroB uses un-namespaced children */
|
||||||
{
|
{
|
||||||
key = &key[1];
|
key = &key[1];
|
||||||
g_string_append_printf (markdown, "<%s>%s</%s>\n", key, escaped, key);
|
g_string_append_printf (markdown, "<%s>", key);
|
||||||
|
string_append_escaped (markdown, value);
|
||||||
|
g_string_append_printf (markdown, "</%s>\n", key);
|
||||||
}
|
}
|
||||||
else if (namespace)
|
else if (namespace)
|
||||||
g_string_append_printf (markup, " %s=\"%s\"", key, escaped);
|
{
|
||||||
|
g_string_append_printf (markup, " %s=\"", key);
|
||||||
|
string_append_escaped (markup, value);
|
||||||
|
g_string_append_c (markup, '\"');
|
||||||
|
}
|
||||||
else
|
else
|
||||||
g_string_append_printf (markup, " midori:%s=\"%s\"", key, escaped);
|
{
|
||||||
g_free (escaped);
|
g_string_append_printf (markup, " midori:%s=\"", key);
|
||||||
|
string_append_escaped (markup, value);
|
||||||
|
g_string_append_c (markup, '\"');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!namespace)
|
if (!namespace)
|
||||||
{
|
{
|
||||||
|
@ -577,46 +625,29 @@ static gchar*
|
||||||
katze_array_to_xbel (KatzeArray* array,
|
katze_array_to_xbel (KatzeArray* array,
|
||||||
GError** error)
|
GError** error)
|
||||||
{
|
{
|
||||||
GString* inner_markup;
|
gchar* metadata = katze_item_metadata_to_xbel (KATZE_ITEM (array));
|
||||||
guint i;
|
guint i;
|
||||||
KatzeItem* item;
|
KatzeItem* item;
|
||||||
gchar* item_xml;
|
|
||||||
const gchar* namespacing;
|
|
||||||
gchar* title;
|
|
||||||
gchar* desc;
|
|
||||||
gchar* metadata;
|
|
||||||
gchar* outer_markup;
|
|
||||||
|
|
||||||
inner_markup = g_string_new (NULL);
|
GString* markup = g_string_new (
|
||||||
i = 0;
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
while ((item = katze_array_get_nth_item (array, i++)))
|
|
||||||
{
|
|
||||||
item_xml = katze_item_to_data (item);
|
|
||||||
g_string_append (inner_markup, item_xml);
|
|
||||||
g_free (item_xml);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespacing = " xmlns:midori=\"http://www.twotoasts.de\"";
|
|
||||||
title = _simple_xml_element ("title", katze_item_get_name (KATZE_ITEM (array)));
|
|
||||||
desc = _simple_xml_element ("desc", katze_item_get_text (KATZE_ITEM (array)));
|
|
||||||
metadata = katze_item_metadata_to_xbel (KATZE_ITEM (array));
|
|
||||||
outer_markup = g_strdup_printf (
|
|
||||||
"%s%s<xbel version=\"1.0\"%s>\n%s%s%s%s</xbel>\n",
|
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
|
||||||
"<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD "
|
"<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD "
|
||||||
"XML Bookmark Exchange Language 1.0//EN//XML\" "
|
"XML Bookmark Exchange Language 1.0//EN//XML\" "
|
||||||
"\"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">\n",
|
"\"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">\n"
|
||||||
namespacing,
|
"<xbel version=\"1.0\""
|
||||||
title,
|
" xmlns:midori=\"http://www.twotoasts.de\""
|
||||||
desc,
|
">\n");
|
||||||
metadata,
|
string_append_xml_element (markup, "title", katze_item_get_name (KATZE_ITEM (array)));
|
||||||
inner_markup->str);
|
string_append_xml_element (markup, "desc", katze_item_get_text (KATZE_ITEM (array)));
|
||||||
g_string_free (inner_markup, TRUE);
|
g_string_append (markup, metadata);
|
||||||
g_free (title);
|
i = 0;
|
||||||
g_free (desc);
|
while ((item = katze_array_get_nth_item (array, i++)))
|
||||||
|
string_append_item (markup, item);
|
||||||
|
g_string_append (markup, "</xbel>\n");
|
||||||
|
|
||||||
g_free (metadata);
|
g_free (metadata);
|
||||||
|
|
||||||
return outer_markup;
|
return g_string_free (markup, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
Loading…
Reference in a new issue