[gnome-software] Split out the appstream markup functionality into its own module
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Split out the appstream markup functionality into its own module
- Date: Mon, 21 Oct 2013 11:58:10 +0000 (UTC)
commit c6f570458d90029059fde270a14a01847f71c25a
Author: Richard Hughes <richard hughsie com>
Date: Mon Oct 21 10:39:07 2013 +0100
Split out the appstream markup functionality into its own module
src/plugins/Makefile.am | 2 +
src/plugins/appstream-markup.c | 202 +++++++++++++++++++++++++++++++++++++++
src/plugins/appstream-markup.h | 62 ++++++++++++
src/plugins/gs-plugin-appdata.c | 163 ++++++--------------------------
4 files changed, 295 insertions(+), 134 deletions(-)
---
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index a5ec830..c2759a8 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -85,6 +85,8 @@ libgs_plugin_appstream_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
libgs_plugin_appdata_la_SOURCES = \
appstream-common.c \
appstream-common.h \
+ appstream-markup.c \
+ appstream-markup.h \
gs-plugin-appdata.c
libgs_plugin_appdata_la_LIBADD = $(GS_PLUGIN_LIBS)
libgs_plugin_appdata_la_LDFLAGS = -module -avoid-version
diff --git a/src/plugins/appstream-markup.c b/src/plugins/appstream-markup.c
new file mode 100644
index 0000000..f3624f3
--- /dev/null
+++ b/src/plugins/appstream-markup.c
@@ -0,0 +1,202 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include "appstream-common.h"
+#include "appstream-markup.h"
+
+struct AppstreamMarkup
+{
+ AppstreamMarkupMode mode;
+ GString *string;
+ gboolean enabled;
+ gchar *lang;
+ guint locale_value;
+};
+
+/**
+ * appstream_markup_free:
+ */
+void
+appstream_markup_free (AppstreamMarkup *app)
+{
+ g_free (app->lang);
+ g_string_free (app->string, TRUE);
+ g_slice_free (AppstreamMarkup, app);
+}
+
+/**
+ * appstream_markup_new:
+ */
+AppstreamMarkup *
+appstream_markup_new (void)
+{
+ AppstreamMarkup *markup;
+ markup = g_slice_new0 (AppstreamMarkup);
+ markup->enabled = TRUE;
+ markup->locale_value = G_MAXUINT;
+ markup->string = g_string_new("");
+ return markup;
+}
+
+/**
+ * appstream_markup_process_locale:
+ */
+static gboolean
+appstream_markup_process_locale (AppstreamMarkup *markup)
+{
+ guint locale_value;
+
+ /* is this worse than the locale we're already showing */
+ locale_value = appstream_get_locale_value (markup->lang);
+ if (locale_value > markup->locale_value)
+ return FALSE;
+
+ /* is this better than the previous locale */
+ if (locale_value < markup->locale_value) {
+ g_debug ("Dumping existing string for locale %s!", markup->lang);
+ g_string_set_size (markup->string, 0);
+ markup->locale_value = locale_value;
+ }
+ return TRUE;
+}
+
+/**
+ * appstream_markup_set_mode:
+ */
+void
+appstream_markup_set_mode (AppstreamMarkup *markup, AppstreamMarkupMode mode)
+{
+ if (!markup->enabled)
+ return;
+
+ /* format markup in the same way as the distro pre-processor */
+ switch (mode) {
+ case APPSTREAM_MARKUP_MODE_P_START:
+ if (appstream_markup_process_locale (markup) &&
+ markup->string->len > 0)
+ g_string_append (markup->string, "\n");
+ markup->mode = APPSTREAM_MARKUP_MODE_P_CONTENT;
+ break;
+ case APPSTREAM_MARKUP_MODE_UL_START:
+ markup->mode = APPSTREAM_MARKUP_MODE_UL_CONTENT;
+ break;
+ case APPSTREAM_MARKUP_MODE_LI_START:
+ markup->mode = APPSTREAM_MARKUP_MODE_LI_CONTENT;
+ break;
+ case APPSTREAM_MARKUP_MODE_START:
+ markup->locale_value = G_MAXUINT;
+ g_string_truncate (markup->string, 0);
+ markup->mode = mode;
+ break;
+ case APPSTREAM_MARKUP_MODE_END:
+ /* remove trailing newline if not distro-formatted */
+ if (markup->mode != APPSTREAM_MARKUP_MODE_START) {
+ g_string_truncate (markup->string,
+ markup->string->len - 1);
+ }
+ markup->mode = mode;
+ break;
+ default:
+ markup->mode = mode;
+ break;
+ }
+}
+
+/**
+ * appstream_markup_add_content:
+ */
+void
+appstream_markup_add_content (AppstreamMarkup *markup,
+ const gchar *text,
+ gssize length)
+{
+ gchar *tmp = NULL;
+
+ if (!markup->enabled)
+ return;
+
+ /* lang not good enough */
+ if (!appstream_markup_process_locale (markup))
+ return;
+
+ switch (markup->mode) {
+ case APPSTREAM_MARKUP_MODE_START:
+ /* this is for pre-formatted text */
+ tmp = appstream_xml_unmunge (text, length);
+ if (tmp == NULL)
+ break;
+ g_string_append_printf (markup->string, "%s", tmp);
+ break;
+ case APPSTREAM_MARKUP_MODE_P_CONTENT:
+ tmp = appstream_xml_unmunge (text, length);
+ if (tmp == NULL)
+ break;
+ g_string_append_printf (markup->string, "%s\n", tmp);
+ break;
+ case APPSTREAM_MARKUP_MODE_LI_CONTENT:
+ tmp = appstream_xml_unmunge (text, length);
+ if (tmp == NULL)
+ break;
+ g_string_append_printf (markup->string, " • %s\n", tmp);
+ break;
+ default:
+ break;
+ }
+ g_free (tmp);
+}
+
+/**
+ * appstream_markup_set_lang:
+ */
+void
+appstream_markup_set_lang (AppstreamMarkup *markup, const gchar *lang)
+{
+ if (!markup->enabled)
+ return;
+ if (lang == NULL)
+ lang = "C";
+ if (g_strcmp0 (lang, markup->lang) == 0)
+ return;
+ g_free (markup->lang);
+ markup->lang = g_strdup (lang);
+}
+
+/**
+ * appstream_markup_get_text:
+ */
+const gchar *
+appstream_markup_get_text (AppstreamMarkup *markup)
+{
+ if (markup->string->len == 0)
+ return NULL;
+ return markup->string->str;
+}
+
+/**
+ * appstream_markup_set_enabled:
+ */
+void
+appstream_markup_set_enabled (AppstreamMarkup *markup, gboolean enabled)
+{
+ markup->enabled = enabled;
+}
diff --git a/src/plugins/appstream-markup.h b/src/plugins/appstream-markup.h
new file mode 100644
index 0000000..65e3973
--- /dev/null
+++ b/src/plugins/appstream-markup.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __APPSTREAM_MARKUP_H
+#define __APPSTREAM_MARKUP_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ APPSTREAM_MARKUP_MODE_START,
+ APPSTREAM_MARKUP_MODE_END,
+ APPSTREAM_MARKUP_MODE_P_START,
+ APPSTREAM_MARKUP_MODE_P_CONTENT,
+ APPSTREAM_MARKUP_MODE_P_END,
+ APPSTREAM_MARKUP_MODE_UL_START,
+ APPSTREAM_MARKUP_MODE_UL_CONTENT,
+ APPSTREAM_MARKUP_MODE_UL_END,
+ APPSTREAM_MARKUP_MODE_LI_START,
+ APPSTREAM_MARKUP_MODE_LI_CONTENT,
+ APPSTREAM_MARKUP_MODE_LI_END,
+ APPSTREAM_MARKUP_MODE_LAST
+} AppstreamMarkupMode;
+
+typedef struct AppstreamMarkup AppstreamMarkup;
+
+AppstreamMarkup *appstream_markup_new (void);
+void appstream_markup_free (AppstreamMarkup *markup);
+void appstream_markup_set_enabled (AppstreamMarkup *markup,
+ gboolean enabled);
+void appstream_markup_set_mode (AppstreamMarkup *markup,
+ AppstreamMarkupMode mode);
+void appstream_markup_set_lang (AppstreamMarkup *markup,
+ const gchar *lang);
+void appstream_markup_add_content (AppstreamMarkup *markup,
+ const gchar *text,
+ gssize length);
+const gchar *appstream_markup_get_text (AppstreamMarkup *markup);
+
+G_END_DECLS
+
+#endif /* __APPSTREAM_MARKUP_H */
+
diff --git a/src/plugins/gs-plugin-appdata.c b/src/plugins/gs-plugin-appdata.c
index f6fa380..223fd49 100644
--- a/src/plugins/gs-plugin-appdata.c
+++ b/src/plugins/gs-plugin-appdata.c
@@ -24,6 +24,7 @@
#include <gs-plugin.h>
#include "appstream-common.h"
+#include "appstream-markup.h"
struct GsPluginPrivate {
gchar *cachedir;
@@ -118,89 +119,13 @@ out:
return ret;
}
-typedef enum {
- APPSTREAM_DESCRIPTION_TAG_START,
- APPSTREAM_DESCRIPTION_TAG_END,
- APPSTREAM_DESCRIPTION_TAG_P_START,
- APPSTREAM_DESCRIPTION_TAG_P_CONTENT,
- APPSTREAM_DESCRIPTION_TAG_P_END,
- APPSTREAM_DESCRIPTION_TAG_UL_START,
- APPSTREAM_DESCRIPTION_TAG_UL_CONTENT,
- APPSTREAM_DESCRIPTION_TAG_UL_END,
- APPSTREAM_DESCRIPTION_TAG_LI_START,
- APPSTREAM_DESCRIPTION_TAG_LI_CONTENT,
- APPSTREAM_DESCRIPTION_TAG_LI_END,
- APPSTREAM_DESCRIPTION_TAG_LAST
-} AppStreamDescriptionTag;
-
typedef struct {
AppstreamTag tag;
GsApp *app;
- GString *string;
- AppStreamDescriptionTag description_tag;
- gchar *lang;
- guint locale_value;
+ AppstreamMarkup *markup;
} AppstreamCacheHelper;
/**
- * appstream_description_build:
- */
-static void
-appstream_description_build (AppstreamCacheHelper *helper,
- AppStreamDescriptionTag tag,
- const gchar *text)
-{
- guint locale_value;
-
- /* we are not interested */
- if (helper->string == NULL)
- return;
-
- /* is this worse than the locale we're already showing */
- locale_value = appstream_get_locale_value (helper->lang);
- if (locale_value > helper->locale_value)
- return;
-
- /* is this better than the previous locale */
- if (locale_value < helper->locale_value) {
- g_debug ("Dumping existing string for locale %s!", helper->lang);
- g_string_set_size (helper->string, 0);
- helper->locale_value = locale_value;
- }
-
-
- /* format markup in the same way as the distro pre-processor */
- switch (tag) {
- case APPSTREAM_DESCRIPTION_TAG_START:
- case APPSTREAM_DESCRIPTION_TAG_P_END:
- case APPSTREAM_DESCRIPTION_TAG_UL_START:
- case APPSTREAM_DESCRIPTION_TAG_UL_CONTENT:
- case APPSTREAM_DESCRIPTION_TAG_UL_END:
- case APPSTREAM_DESCRIPTION_TAG_LI_START:
- case APPSTREAM_DESCRIPTION_TAG_LI_END:
- /* ignore */
- break;
- case APPSTREAM_DESCRIPTION_TAG_END:
- /* remove trailing newline */
- g_string_truncate (helper->string, helper->string->len - 1);
- break;
- break;
- case APPSTREAM_DESCRIPTION_TAG_P_CONTENT:
- g_string_append_printf (helper->string, "%s\n", text);
- break;
- case APPSTREAM_DESCRIPTION_TAG_LI_CONTENT:
- g_string_append_printf (helper->string, " • %s\n", text);
- break;
- case APPSTREAM_DESCRIPTION_TAG_P_START:
- if (helper->string->len > 0)
- g_string_append (helper->string, "\n");
- break;
- default:
- break;
- }
-}
-
-/**
* appdata_parse_start_element_cb:
*/
static void
@@ -212,42 +137,26 @@ appdata_parse_start_element_cb (GMarkupParseContext *context,
GError **error)
{
AppstreamCacheHelper *helper = (AppstreamCacheHelper *) user_data;
- const gchar *lang_tmp = NULL;
guint i;
/* description markup */
if (helper->tag == APPSTREAM_TAG_DESCRIPTION) {
-
- /* save xml:lang if different to existing */
for (i = 0; attribute_names[i] != NULL; i++) {
if (g_strcmp0 (attribute_names[i], "xml:lang") == 0) {
- lang_tmp = attribute_values[i];
+ appstream_markup_set_lang (helper->markup,
+ attribute_values[i]);
break;
}
}
- if (lang_tmp == NULL)
- lang_tmp = "C";
- if (g_strcmp0 (lang_tmp, helper->lang) != 0) {
- g_free (helper->lang);
- helper->lang = g_strdup (lang_tmp);
- }
-
- /* build string */
if (g_strcmp0 (element_name, "p") == 0) {
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_P_START,
- NULL);
- helper->description_tag = APPSTREAM_DESCRIPTION_TAG_P_CONTENT;
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_P_START);
} else if (g_strcmp0 (element_name, "ul") == 0) {
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_UL_START,
- NULL);
- helper->description_tag = APPSTREAM_DESCRIPTION_TAG_UL_CONTENT;
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_UL_START);
} else if (g_strcmp0 (element_name, "li") == 0) {
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_LI_START,
- NULL);
- helper->description_tag = APPSTREAM_DESCRIPTION_TAG_LI_CONTENT;
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_LI_START);
}
return;
}
@@ -255,14 +164,12 @@ appdata_parse_start_element_cb (GMarkupParseContext *context,
helper->tag = appstream_tag_from_string (element_name);
switch (helper->tag) {
case APPSTREAM_TAG_DESCRIPTION:
- helper->string = NULL;
/* only process the description if it's not already been set;
* doing all this string munging is moderately expensive */
- if (gs_app_get_description (helper->app) == NULL)
- helper->string = g_string_new ("");
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_START,
- NULL);
+ appstream_markup_set_enabled (helper->markup,
+ gs_app_get_description (helper->app) == NULL);
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_START);
break;
case APPSTREAM_TAG_UNKNOWN:
g_warning ("AppData: tag %s unknown", element_name);
@@ -282,31 +189,24 @@ appdata_parse_end_element_cb (GMarkupParseContext *context,
gpointer user_data,
GError **error)
{
+ const gchar *tmp;
AppstreamCacheHelper *helper = (AppstreamCacheHelper *) user_data;
if (helper->tag == APPSTREAM_TAG_DESCRIPTION) {
if (g_strcmp0 (element_name, "p") == 0) {
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_P_END,
- NULL);
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_P_END);
} else if (g_strcmp0 (element_name, "ul") == 0) {
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_UL_END,
- NULL);
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_UL_END);
} else if (g_strcmp0 (element_name, "li") == 0) {
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_LI_END,
- NULL);
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_LI_END);
} else if (g_strcmp0 (element_name, "description") == 0) {
- appstream_description_build (helper,
- APPSTREAM_DESCRIPTION_TAG_END,
- NULL);
- if (helper->string != NULL) {
- g_debug ("AppData: Setting description: %s",
- helper->string->str);
- gs_app_set_description (helper->app,
- helper->string->str);
- g_string_free (helper->string, TRUE);
- }
+ appstream_markup_set_mode (helper->markup,
+ APPSTREAM_MARKUP_MODE_END);
+ tmp = appstream_markup_get_text (helper->markup);
+ if (tmp != NULL)
+ gs_app_set_description (helper->app, tmp);
helper->tag = APPSTREAM_TAG_APPLICATION;
}
} else {
@@ -341,12 +241,7 @@ appdata_parse_text_cb (GMarkupParseContext *context,
/* ignore */
break;
case APPSTREAM_TAG_DESCRIPTION:
- tmp = appstream_xml_unmunge (text, text_len);
- if (tmp == NULL)
- break;
- appstream_description_build (helper,
- helper->description_tag,
- tmp);
+ appstream_markup_add_content (helper->markup, text, text_len);
break;
case APPSTREAM_TAG_SCREENSHOT:
/* FIXME: actually add to API */
@@ -430,7 +325,7 @@ gs_plugin_refine_by_local_appdata (GsApp *app,
/* parse file */
helper = g_new0 (AppstreamCacheHelper, 1);
helper->app = app;
- helper->locale_value = G_MAXUINT;
+ helper->markup = appstream_markup_new ();
ctx = g_markup_parse_context_new (&parser,
G_MARKUP_PREFIX_ERROR_POSITION,
helper,
@@ -442,7 +337,7 @@ out:
if (ctx != NULL)
g_markup_parse_context_free (ctx);
if (helper != NULL)
- g_free (helper->lang);
+ appstream_markup_free (helper->markup);
g_free (helper);
g_free (data);
return ret;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]