summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun McCance <shaunm@shaunmlxlap.localdomain>2009-06-09 19:28:02 -0500
committerShaun McCance <shaunm@shaunmlxlap.localdomain>2009-06-09 19:28:02 -0500
commit2b4f4264f62827092f02e03d9f50bda29241fcf5 (patch)
tree4ff897d8564cb1350d4761afeb0a6c095b51b30f
parent752f2f834554eab6c297f72041dbb806a51a74a9 (diff)
downloadyelp-2b4f4264f62827092f02e03d9f50bda29241fcf5.tar.gz
Implemented cache for Mallard documents
-rw-r--r--src/yelp-mallard.c188
-rw-r--r--src/yelp-transform.c34
-rw-r--r--src/yelp-transform.h3
-rw-r--r--stylesheets/mal2html.xsl.in25
4 files changed, 215 insertions, 35 deletions
diff --git a/src/yelp-mallard.c b/src/yelp-mallard.c
index 30a5f639..783b06d6 100644
--- a/src/yelp-mallard.c
+++ b/src/yelp-mallard.c
@@ -38,6 +38,7 @@
#include "yelp-debug.h"
#define STYLESHEET DATADIR"/yelp/xslt/mal2html.xsl"
+#define MALLARD_NS "http://www.gnome.org/~shaunm/mallard"
#define YELP_MALLARD_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_MALLARD, YelpMallardPriv))
@@ -54,6 +55,11 @@ typedef struct {
gchar *filename;
xmlDocPtr xmldoc;
YelpTransform *transform;
+
+ xmlNodePtr cur;
+ xmlNodePtr cache;
+ gboolean link_title;
+ gboolean sort_title;
} MallardPageData;
struct _YelpMallardPriv {
@@ -66,6 +72,8 @@ struct _YelpMallardPriv {
gint transforms_running;
GSList *pending;
+ xmlDocPtr cache;
+ xmlNsPtr cache_ns;
GHashTable *pages_hash;
};
@@ -95,11 +103,13 @@ static void transform_final_func (YelpTransform *transform,
MallardPageData *page_data);
/* Other */
static void mallard_think (YelpMallard *mallard);
-static void mallard_pending (YelpMallard *mallard);
static void mallard_try_run (YelpMallard *mallard,
gchar *page_id);
static void mallard_page_data_walk (MallardPageData *page_data);
+static void mallard_page_data_info (MallardPageData *page_data,
+ xmlNodePtr info_node,
+ xmlNodePtr cache_node);
static void mallard_page_data_run (MallardPageData *page_data);
static void mallard_page_data_free (MallardPageData *page_data);
@@ -147,6 +157,7 @@ static void
mallard_init (YelpMallard *mallard)
{
YelpMallardPriv *priv;
+ xmlNodePtr cur;
priv = mallard->priv = YELP_MALLARD_GET_PRIVATE (mallard);
priv->mutex = g_mutex_new ();
@@ -154,6 +165,12 @@ mallard_init (YelpMallard *mallard)
priv->thread_running = FALSE;
priv->transforms_running = 0;
+ priv->cache = xmlNewDoc (BAD_CAST "1.0");
+ priv->cache_ns = xmlNewNs (NULL, BAD_CAST MALLARD_NS, BAD_CAST "mal");
+ cur = xmlNewDocNode (priv->cache, priv->cache_ns, BAD_CAST "cache", NULL);
+ xmlDocSetRootElement (priv->cache, cur);
+ priv->cache_ns->next = cur->nsDef;
+ cur->nsDef = priv->cache_ns;
priv->pages_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL,
(GDestroyNotify) mallard_page_data_free);
@@ -331,22 +348,8 @@ mallard_think (YelpMallard *mallard)
g_object_unref (pageinfo);
}
- mallard_pending (mallard);
-
- done:
- g_object_unref (children);
- g_object_unref (gfile);
-
- priv->thread_running = FALSE;
- g_object_unref (mallard);
-}
-
-static void
-mallard_pending (YelpMallard *mallard)
-{
- YelpMallardPriv *priv = mallard->priv;
-
g_mutex_lock (priv->mutex);
+ priv->state = MALLARD_STATE_IDLE;
while (priv->pending) {
gchar *page_id;
page_id = (gchar *) priv->pending->data;
@@ -355,6 +358,13 @@ mallard_pending (YelpMallard *mallard)
priv->pending = g_slist_delete_link (priv->pending, priv->pending);
}
g_mutex_unlock (priv->mutex);
+
+ done:
+ g_object_unref (children);
+ g_object_unref (gfile);
+
+ priv->thread_running = FALSE;
+ g_object_unref (mallard);
}
static void
@@ -366,7 +376,7 @@ mallard_try_run (YelpMallard *mallard,
page_data = g_hash_table_lookup (mallard->priv->pages_hash, page_id);
if (page_data == NULL) {
- printf ("FIXME: page not foun\n");
+ printf ("FIXME: page not found\n");
return;
}
@@ -380,30 +390,142 @@ static void
mallard_page_data_walk (MallardPageData *page_data)
{
xmlParserCtxtPtr parserCtxt = NULL;
- xmlNodePtr cur;
xmlChar *id;
- parserCtxt = xmlNewParserCtxt ();
- page_data->xmldoc = xmlCtxtReadFile (parserCtxt,
- (const char *) page_data->filename, NULL,
- XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
- XML_PARSE_NOENT | XML_PARSE_NONET );
- if (page_data->xmldoc == NULL)
- goto done;
+ if (page_data->cur == NULL) {
+ parserCtxt = xmlNewParserCtxt ();
+ page_data->xmldoc = xmlCtxtReadFile (parserCtxt,
+ (const char *) page_data->filename, NULL,
+ XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
+ XML_PARSE_NOENT | XML_PARSE_NONET );
+ if (page_data->xmldoc == NULL)
+ goto done;
+ page_data->cur = xmlDocGetRootElement (page_data->xmldoc);
+ page_data->cache = xmlDocGetRootElement (page_data->mallard->priv->cache);
+ mallard_page_data_walk (page_data);
+ } else {
+ xmlNodePtr child, oldcur, oldcache, info;
- cur = xmlDocGetRootElement (page_data->xmldoc);
- id = xmlGetProp (cur, BAD_CAST "id");
- if (id == NULL)
- goto done;
- page_data->page_id = g_strdup ((gchar *) id);
- xmlFree (id);
+ id = xmlGetProp (page_data->cur, BAD_CAST "id");
+ if (id == NULL)
+ goto done;
+
+ page_data->cache = xmlNewChild (page_data->cache,
+ page_data->mallard->priv->cache_ns,
+ page_data->cur->name,
+ NULL);
+
+ if (xmlStrEqual (page_data->cur->name, BAD_CAST "page")) {
+ page_data->page_id = g_strdup ((gchar *) id);
+ xmlSetProp (page_data->cache, BAD_CAST "id", id);
+ } else {
+ gchar *newid = g_strdup_printf ("%s#%s", page_data->page_id, id);
+ xmlSetProp (page_data->cache, BAD_CAST "id", BAD_CAST newid);
+ g_free (newid);
+ }
+
+ info = xmlNewChild (page_data->cache,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "info", NULL);
+ for (child = page_data->cur->children; child; child = child->next) {
+ if (child->type != XML_ELEMENT_NODE)
+ continue;
+ oldcur = page_data->cur;
+ oldcache = page_data->cache;
+ if (xmlStrEqual (child->name, BAD_CAST "info")) {
+ page_data->link_title = FALSE;
+ page_data->sort_title = FALSE;
+ mallard_page_data_info (page_data, child, info);
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "title")) {
+ xmlNodePtr node;
+ xmlNodePtr title_node = xmlNewChild (page_data->cache,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+ if (!page_data->link_title) {
+ xmlNodePtr title_node = xmlNewChild (info,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ xmlSetProp (title_node, BAD_CAST "type", BAD_CAST "link");
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+ }
+ if (!page_data->sort_title) {
+ xmlNodePtr title_node = xmlNewChild (info,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ xmlSetProp (title_node, BAD_CAST "type", BAD_CAST "sort");
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+ }
+ else { printf ("FOO\n"); }
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "section")) {
+ page_data->cur = child;
+ mallard_page_data_walk (page_data);
+ }
+ page_data->cur = oldcur;
+ page_data->cache = oldcache;
+ }
+ }
done:
+ if (id)
+ xmlFree (id);
if (parserCtxt)
xmlFreeParserCtxt (parserCtxt);
}
static void
+mallard_page_data_info (MallardPageData *page_data,
+ xmlNodePtr info_node,
+ xmlNodePtr cache_node)
+{
+ xmlNodePtr child;
+
+ for (child = info_node->children; child; child = child->next) {
+ if (xmlStrEqual (child->name, BAD_CAST "info")) {
+ mallard_page_data_info (page_data, child, cache_node);
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "title")) {
+ xmlNodePtr node, title_node;
+ xmlChar *type, *role;
+ title_node = xmlNewChild (cache_node,
+ page_data->mallard->priv->cache_ns,
+ BAD_CAST "title", NULL);
+ for (node = child->children; node; node = node->next) {
+ xmlAddChild (title_node, xmlCopyNode (node, 1));
+ }
+
+ type = xmlGetProp (child, BAD_CAST "type");
+ role = xmlGetProp (child, BAD_CAST "role");
+
+ if (xmlStrEqual (type, BAD_CAST "link") && role == NULL)
+ page_data->link_title = TRUE;
+ if (xmlStrEqual (type, BAD_CAST "sort"))
+ page_data->sort_title = TRUE;
+
+ if (type) {
+ xmlSetProp (page_data->cache, BAD_CAST "type", BAD_CAST type);
+ xmlFree (type);
+ }
+ if (role) {
+ xmlSetProp (page_data->cache, BAD_CAST "role", BAD_CAST type);
+ xmlFree (role);
+ }
+ }
+ else if (xmlStrEqual (child->name, BAD_CAST "desc")) {
+ xmlAddChild (cache_node, xmlCopyNode (child, 1));
+ }
+ }
+}
+
+static void
mallard_page_data_run (MallardPageData *page_data)
{
gint params_i = 0;
@@ -417,6 +539,10 @@ mallard_page_data_run (MallardPageData *page_data)
params = g_new0 (gchar *, params_max);
yelp_settings_params (&params, &params_i, &params_max);
params[params_i+1] = NULL;
+
+ yelp_transform_set_input (page_data->transform,
+ page_data->mallard->priv->cache);
+
yelp_transform_start (page_data->transform,
page_data->xmldoc,
params);
diff --git a/src/yelp-transform.c b/src/yelp-transform.c
index 3e33f3c0..38e7a88d 100644
--- a/src/yelp-transform.c
+++ b/src/yelp-transform.c
@@ -29,6 +29,8 @@
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/xinclude.h>
+#include <libxml/xpathInternals.h>
+#include <libxslt/documents.h>
#include <libxslt/xslt.h>
#include <libexslt/exslt.h>
#include <libxslt/templates.h>
@@ -62,6 +64,8 @@ static void xslt_yelp_cache (xsltTransformContextPtr ctxt,
xmlNodePtr node,
xmlNodePtr inst,
xsltStylePreCompPtr comp);
+static void xslt_yelp_input (xmlXPathParserContextPtr ctxt,
+ int nargs);
/******************************************************************************/
@@ -98,6 +102,13 @@ YelpTransform
}
void
+yelp_transform_set_input (YelpTransform *transform,
+ xmlDocPtr input)
+{
+ transform->input = input;
+}
+
+void
yelp_transform_start (YelpTransform *transform,
xmlDocPtr document,
gchar **params)
@@ -130,6 +141,10 @@ yelp_transform_start (YelpTransform *transform,
BAD_CAST "cache",
BAD_CAST YELP_NAMESPACE,
(xsltTransformFunction) xslt_yelp_cache);
+ xsltRegisterExtFunction (transform->context,
+ BAD_CAST "input",
+ BAD_CAST YELP_NAMESPACE,
+ (xmlXPathFunction) xslt_yelp_input);
transform->mutex = g_mutex_new ();
g_mutex_lock (transform->mutex);
@@ -431,3 +446,22 @@ xslt_yelp_cache (xsltTransformContextPtr ctxt,
xsltStylePreCompPtr comp)
{
}
+
+static void
+xslt_yelp_input (xmlXPathParserContextPtr ctxt, int nargs)
+{
+ xsltDocumentPtr idoc;
+ xsltTransformContextPtr tctxt;
+ xmlXPathObjectPtr ret;
+ YelpTransform *transform;
+
+ tctxt = xsltXPathGetTransformContext (ctxt);
+ transform = (YelpTransform *) tctxt->_private;
+
+ /* FIXME: pretty sure this eats transform->input, memory corruption will follow */
+ idoc = xsltNewDocument (tctxt, transform->input);
+
+ ret = xmlXPathNewNodeSet (xmlDocGetRootElement (transform->input));
+ xsltExtensionInstructionResultRegister (tctxt, ret);
+ valuePush (ctxt, ret);
+}
diff --git a/src/yelp-transform.h b/src/yelp-transform.h
index e1262e39..f5c30e0b 100644
--- a/src/yelp-transform.h
+++ b/src/yelp-transform.h
@@ -48,6 +48,7 @@ struct _YelpTransform {
xmlDocPtr outputDoc;
xsltStylesheetPtr stylesheet;
xsltTransformContextPtr context;
+ xmlDocPtr input;
YelpTransformFunc func;
@@ -74,6 +75,8 @@ YelpTransform *yelp_transform_new (gchar *stylesheet,
void yelp_transform_start (YelpTransform *transform,
xmlDocPtr document,
gchar **params);
+void yelp_transform_set_input (YelpTransform *transform,
+ xmlDocPtr input);
gchar * yelp_transform_eat_chunk (YelpTransform *transform,
gchar *chunk_id);
void yelp_transform_release (YelpTransform *transform);
diff --git a/stylesheets/mal2html.xsl.in b/stylesheets/mal2html.xsl.in
index 303ac03e..fb76980f 100644
--- a/stylesheets/mal2html.xsl.in
+++ b/stylesheets/mal2html.xsl.in
@@ -1,6 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?><!-- -*- indent-tabs-mode: nil -*- -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:yelp="http://www.gnome.org/yelp/ns"
+ xmlns:mal="http://www.gnome.org/~shaunm/mallard"
xmlns="http://www.w3.org/1999/xhtml"
extension-element-prefixes="yelp"
version="1.0">
@@ -15,6 +16,9 @@
<xsl:param name="mal.chunk.chunk_top" select="true()"/>
<xsl:param name="mal.chunk.extension" select="''"/>
+<xsl:param name="mal.cache" select="yelp:input()"/>
+<xsl:key name="mal.cache.key" match="mal:page | mal:section" use="@id"/>
+
<!-- == mal.chunk == -->
<xsl:template name="mal.chunk">
@@ -26,14 +30,27 @@
</xsl:template>
<!-- == mal.link.target == -->
-<!--
-<xsl:template name="mal.xref.target">
+<xsl:template name="mal.link.target">
<xsl:param name="link" select="."/>
<xsl:param name="xref" select="$link/@xref"/>
<xsl:param name="href" select="$link/@href"/>
- FIXME
+ <xsl:choose>
+ <xsl:when test="string($xref) = ''">
+ <xsl:value-of select="$href"/>
+ </xsl:when>
+ <xsl:when test="contains($xref, '/')">
+ <xsl:value-of select="$href"/>
+ </xsl:when>
+ <xsl:when test="contains($xref, '#')">
+ <xsl:variable name="pageid" select="substring-before($xref, '#')"/>
+ <xsl:variable name="sectionid" select="substring-after($xref, '#')"/>
+ <xsl:value-of select="concat('#', $pageid, '/', $sectionid)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('#', $xref)"/>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
--->
<!-- == mal2html.css.custom == -->
<xsl:template name="mal2html.css.custom">