[tracker/wip/carlosg/http-endpoint: 3/10] libtracker-sparql: Add private XML serializer task
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/http-endpoint: 3/10] libtracker-sparql: Add private XML serializer task
- Date: Sat, 12 Dec 2020 20:24:28 +0000 (UTC)
commit ca56fbbf6927d80c191d78b2f29fa6a8681e200a
Author: Carlos Garnacho <carlosg gnome org>
Date: Sat Dec 12 15:55:47 2020 +0100
libtracker-sparql: Add private XML serializer task
This object takes care of serializing cursors into
application/sparql-results+xml format.
docs/reference/libtracker-sparql/meson.build | 1 +
src/libtracker-sparql/meson.build | 3 +-
src/libtracker-sparql/tracker-serializer-xml.c | 256 +++++++++++++++++++++++++
src/libtracker-sparql/tracker-serializer-xml.h | 36 ++++
4 files changed, 295 insertions(+), 1 deletion(-)
---
diff --git a/docs/reference/libtracker-sparql/meson.build b/docs/reference/libtracker-sparql/meson.build
index d5817657c..cc9c793a9 100644
--- a/docs/reference/libtracker-sparql/meson.build
+++ b/docs/reference/libtracker-sparql/meson.build
@@ -39,6 +39,7 @@ private_headers = [
'tracker-private.h',
'tracker-serializer.h',
'tracker-serializer-json.h',
+ 'tracker-serializer-xml.h',
'direct',
'bus',
'remote',
diff --git a/src/libtracker-sparql/meson.build b/src/libtracker-sparql/meson.build
index 55248ac38..0e6064e67 100644
--- a/src/libtracker-sparql/meson.build
+++ b/src/libtracker-sparql/meson.build
@@ -27,6 +27,7 @@ libtracker_sparql_c_sources = files(
'tracker-statement.c',
'tracker-serializer.c',
'tracker-serializer-json.c',
+ 'tracker-serializer-xml.c',
'tracker-uri.c',
'tracker-utils.c',
'tracker-version.c',
@@ -51,7 +52,7 @@ libtracker_sparql_c_public_headers = files(
libtracker_sparql_intermediate = static_library('tracker-sparql-intermediate',
enum_types,
libtracker_sparql_c_sources,
- dependencies: [tracker_common_dep, json_glib],
+ dependencies: [tracker_common_dep, json_glib, libxml2],
gnu_symbol_visibility: 'hidden',
)
diff --git a/src/libtracker-sparql/tracker-serializer-xml.c b/src/libtracker-sparql/tracker-serializer-xml.c
new file mode 100644
index 000000000..3dbfc3806
--- /dev/null
+++ b/src/libtracker-sparql/tracker-serializer-xml.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2020, Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "config.h"
+
+#include "tracker-serializer-xml.h"
+
+#include <libxml/xmlwriter.h>
+
+struct _TrackerSerializerXml
+{
+ TrackerSerializer parent_instance;
+ xmlBufferPtr buffer;
+ xmlTextWriterPtr writer;
+ GPtrArray *vars;
+ gssize current_pos;
+
+ guint stream_closed : 1;
+ guint cursor_started : 1;
+ guint cursor_finished : 1;
+ guint head_printed : 1;
+};
+
+G_DEFINE_TYPE (TrackerSerializerXml, tracker_serializer_xml,
+ TRACKER_TYPE_SERIALIZER)
+
+static void
+tracker_serializer_xml_finalize (GObject *object)
+{
+ g_input_stream_close (G_INPUT_STREAM (object), NULL, NULL);
+
+ G_OBJECT_CLASS (tracker_serializer_xml_parent_class)->finalize (object);
+}
+
+static gboolean
+serialize_up_to_position (TrackerSerializerXml *serializer_xml,
+ gsize pos,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerSparqlCursor *cursor;
+ GError *inner_error = NULL;
+ gint i;
+
+ if (!serializer_xml->buffer)
+ serializer_xml->buffer = xmlBufferCreate ();
+ if (!serializer_xml->writer)
+ serializer_xml->writer = xmlNewTextWriterMemory (serializer_xml->buffer, 0);
+ if (!serializer_xml->vars)
+ serializer_xml->vars = g_ptr_array_new_with_free_func (g_free);
+
+ cursor = tracker_serializer_get_cursor (TRACKER_SERIALIZER (serializer_xml));
+
+ if (!serializer_xml->head_printed) {
+ xmlTextWriterStartDocument (serializer_xml->writer, "1.0", "UTF-8", NULL);
+ xmlTextWriterStartElement (serializer_xml->writer, "sparql");
+
+ xmlTextWriterStartElement (serializer_xml->writer, "head");
+
+ for (i = 0; i < tracker_sparql_cursor_get_n_columns (cursor); i++) {
+ const gchar *var;
+
+ var = tracker_sparql_cursor_get_variable_name (cursor, i);
+ xmlTextWriterStartElement (serializer_xml->writer, "variable");
+
+ if (var && *var) {
+ g_ptr_array_add (serializer_xml->vars,
+ g_strdup (var));
+ } else {
+ g_ptr_array_add (serializer_xml->vars,
+ g_strdup_printf ("var%d", i + 1));
+ }
+
+ xmlTextWriterWriteFormatAttribute (serializer_xml->writer,
+ "name",
+ "%s",
+ (gchar *) g_ptr_array_index (serializer_xml->vars,
i));
+ xmlTextWriterEndElement (serializer_xml->writer);
+ }
+
+ xmlTextWriterEndElement (serializer_xml->writer);
+ xmlTextWriterStartElement (serializer_xml->writer, "results");
+ serializer_xml->head_printed = TRUE;
+ }
+
+ while (!serializer_xml->cursor_finished &&
+ xmlBufferLength (serializer_xml->buffer) < pos) {
+ if (!tracker_sparql_cursor_next (cursor, cancellable, &inner_error)) {
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ } else {
+ xmlTextWriterEndElement (serializer_xml->writer);
+ xmlTextWriterEndElement (serializer_xml->writer);
+ xmlTextWriterEndDocument (serializer_xml->writer);
+ serializer_xml->cursor_finished = TRUE;
+ break;
+ }
+ } else {
+ serializer_xml->cursor_started = TRUE;
+ }
+
+ xmlTextWriterStartElement (serializer_xml->writer, "result");
+
+ for (i = 0; i < tracker_sparql_cursor_get_n_columns (cursor); i++) {
+ const gchar *var, *str, *type, *datatype = NULL;
+
+ if (tracker_sparql_cursor_get_value_type (cursor, i) ==
TRACKER_SPARQL_VALUE_TYPE_UNBOUND)
+ continue;
+
+ var = g_ptr_array_index (serializer_xml->vars, i);
+
+ xmlTextWriterStartElement (serializer_xml->writer, "binding");
+ xmlTextWriterWriteFormatAttribute (serializer_xml->writer,
+ "name",
+ "%s",
+ var);
+
+ switch (tracker_sparql_cursor_get_value_type (cursor, i)) {
+ case TRACKER_SPARQL_VALUE_TYPE_URI:
+ type = "uri";
+ break;
+ case TRACKER_SPARQL_VALUE_TYPE_STRING:
+ type = "literal";
+ datatype = TRACKER_PREFIX_XSD "string";
+ break;
+ case TRACKER_SPARQL_VALUE_TYPE_INTEGER:
+ case TRACKER_SPARQL_VALUE_TYPE_BOOLEAN:
+ type = "literal";
+ datatype = TRACKER_PREFIX_XSD "integer";
+ break;
+ case TRACKER_SPARQL_VALUE_TYPE_DOUBLE:
+ type = "literal";
+ datatype = TRACKER_PREFIX_XSD "double";
+ break;
+ case TRACKER_SPARQL_VALUE_TYPE_DATETIME:
+ type = "literal";
+ datatype = TRACKER_PREFIX_XSD "dateTime";
+ break;
+ case TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE:
+ type = "bnode";
+ break;
+ default:
+ g_warn_if_reached ();
+ break;
+ }
+
+ xmlTextWriterStartElement (serializer_xml->writer, type);
+
+ if (datatype) {
+ xmlTextWriterWriteFormatAttribute (serializer_xml->writer,
+ "datatype",
+ "%s",
+ datatype);
+ }
+
+ str = tracker_sparql_cursor_get_string (cursor, i, NULL);
+
+ if (str) {
+ xmlTextWriterWriteRaw (serializer_xml->writer, str);
+ }
+
+ xmlTextWriterEndElement (serializer_xml->writer);
+ xmlTextWriterEndElement (serializer_xml->writer);
+ }
+
+ xmlTextWriterEndElement (serializer_xml->writer);
+ }
+
+ return TRUE;
+}
+
+static gssize
+tracker_serializer_xml_read (GInputStream *istream,
+ gpointer buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerSerializerXml *serializer_xml = TRACKER_SERIALIZER_XML (istream);
+ gsize bytes_unflushed, bytes_copied;
+ const xmlChar *xml_buf;
+
+ if (serializer_xml->stream_closed ||
+ (serializer_xml->cursor_finished &&
+ serializer_xml->current_pos == xmlBufferLength (serializer_xml->buffer)))
+ return 0;
+
+ if (!serialize_up_to_position (serializer_xml,
+ serializer_xml->current_pos + count,
+ cancellable,
+ error))
+ return -1;
+
+ bytes_unflushed =
+ xmlBufferLength (serializer_xml->buffer) - serializer_xml->current_pos;
+ bytes_copied = MIN (count, bytes_unflushed);
+
+ xml_buf = xmlBufferContent (serializer_xml->buffer);
+
+ memcpy (buffer,
+ &xml_buf[serializer_xml->current_pos],
+ bytes_copied);
+ serializer_xml->current_pos += bytes_copied;
+
+ return bytes_copied;
+}
+
+static gboolean
+tracker_serializer_xml_close (GInputStream *istream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ TrackerSerializerXml *serializer_xml = TRACKER_SERIALIZER_XML (istream);
+
+ serializer_xml->stream_closed = TRUE;
+ g_clear_pointer (&serializer_xml->buffer, xmlBufferFree);
+ g_clear_pointer (&serializer_xml->writer, xmlFreeTextWriter);
+
+ return TRUE;
+}
+
+static void
+tracker_serializer_xml_class_init (TrackerSerializerXmlClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS (klass);
+
+ object_class->finalize = tracker_serializer_xml_finalize;
+
+ istream_class->read_fn = tracker_serializer_xml_read;
+ istream_class->close_fn = tracker_serializer_xml_close;
+}
+
+static void
+tracker_serializer_xml_init (TrackerSerializerXml *serializer)
+{
+}
diff --git a/src/libtracker-sparql/tracker-serializer-xml.h b/src/libtracker-sparql/tracker-serializer-xml.h
new file mode 100644
index 000000000..d94bf4eb6
--- /dev/null
+++ b/src/libtracker-sparql/tracker-serializer-xml.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020, Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef TRACKER_SERIALIZER_XML_H
+#define TRACKER_SERIALIZER_XML_H
+
+#include <libtracker-sparql/tracker-sparql.h>
+#include <libtracker-sparql/tracker-private.h>
+#include <libtracker-sparql/tracker-serializer.h>
+
+#define TRACKER_TYPE_SERIALIZER_XML (tracker_serializer_xml_get_type())
+
+G_DECLARE_FINAL_TYPE (TrackerSerializerXml,
+ tracker_serializer_xml,
+ TRACKER, SERIALIZER_XML,
+ TrackerSerializer);
+
+#endif /* TRACKER_SERIALIZER_XML_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]