glibrdf

GLib wrapper for the Redland RDF library
git clone https://code.djc.id.au/git/glibrdf/
commit fcfeefe314ac14302941aa0a05095df1fd690e84
parent f05ad706815ae3c0915d540f345a973fe92e838f
Author: Dan Callaghan <djc@djc.id.au>
Date:   Sat, 21 Jul 2012 21:20:19 +1000

new method to return literal value converted to a suitable glib type

Diffstat:
MMakefile | 2+-
Mglibrdf.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mglibrdf.h | 1+
Mglibrdf.vapi | 2++
4 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
@@ -13,7 +13,7 @@ REQUIRES = glib-2.0 gobject-2.0 raptor2 redland
 
 CC = gcc
 CFLAGS ?= -g -O -Wall
-CFLAGS += -fPIC -std=c99 $(shell pkg-config --cflags $(REQUIRES))
+CFLAGS += -fPIC -std=c99 -D_XOPEN_SOURCE $(shell pkg-config --cflags $(REQUIRES))
 LD = gcc
 LDFLAGS ?= -Wl,--as-needed -Wl,-O1
 LIBS = $(shell pkg-config --libs $(REQUIRES))
diff --git a/glibrdf.c b/glibrdf.c
@@ -1,4 +1,6 @@
 
+#include <stdbool.h>
+#include <time.h>
 #include "glibrdf.h"
 
 GType librdf_node_get_gtype(void) {
@@ -11,3 +13,55 @@ GType librdf_node_get_gtype(void) {
     }
     return _librdf_node_type_id;
 }
+
+// glib should do this for me >:(
+static GDate *parse_iso8601_date(const gchar *s) {
+    struct tm tm;
+    if (*strptime(s, "%Y-%m-%d", &tm) != '\0')
+        return NULL;
+    return g_date_new_dmy(tm.tm_mday, 1 + tm.tm_mon, 1900 + tm.tm_year);
+}
+
+// XXX handle parse failures more gracefully?
+// XXX should have some kind of registry so that callers can add new types
+void librdf_node_get_literal_gvalue(librdf_node *node, GValue *value_out) {
+    g_return_if_fail(librdf_node_is_literal(node));
+    const gchar *lv = (const gchar *)librdf_node_get_literal_value(node);
+    g_return_if_fail(lv != NULL);
+    librdf_uri *datatype_uri = librdf_node_get_literal_value_datatype_uri(node);
+    if (datatype_uri == NULL) {
+        g_value_init(value_out, G_TYPE_STRING);
+        g_value_set_string(value_out, lv);
+        return;
+    }
+    const gchar *datatype_uri_string =
+        (const gchar *)librdf_uri_as_string(datatype_uri);
+    if (g_strcmp0(datatype_uri_string,
+            "http://www.w3.org/2001/XMLSchema#integer") == 0) {
+        g_value_init(value_out, G_TYPE_INT64);
+        gchar *lv_unconsumed;
+        g_value_set_int64(value_out, g_ascii_strtoll(lv, &lv_unconsumed, 10));
+        g_return_if_fail(*lv_unconsumed == '\0');
+        return;
+    }
+    if (g_strcmp0(datatype_uri_string,
+            "http://www.w3.org/TR/xmlschema-2/#date") == 0) {
+        GDate *date = parse_iso8601_date(lv);
+        g_return_if_fail(date != NULL);
+        g_value_init(value_out, G_TYPE_DATE);
+        g_value_set_boxed(value_out, date);
+        return;
+    }
+    if (g_strcmp0(datatype_uri_string,
+            "http://www.w3.org/TR/xmlschema-2/#datetime") == 0) {
+        GTimeVal tv;
+        bool parsed = g_time_val_from_iso8601(lv, &tv);
+        g_return_if_fail(parsed);
+        g_value_init(value_out, G_TYPE_DATE_TIME);
+        g_value_set_boxed(value_out, g_date_time_new_from_timeval_utc(&tv));
+        return;
+    }
+    g_warning("Unhandled RDF type %s", librdf_uri_as_string(datatype_uri));
+    g_value_init(value_out, G_TYPE_STRING);
+    g_value_set_string(value_out, lv);
+}
diff --git a/glibrdf.h b/glibrdf.h
@@ -7,5 +7,6 @@
 
 GType librdf_node_get_gtype(void);
 #define G_TYPE_RDF_NODE librdf_node_get_gtype()
+void librdf_node_get_literal_gvalue(librdf_node *node, GValue *value_out);
 
 #endif
diff --git a/glibrdf.vapi b/glibrdf.vapi
@@ -449,6 +449,8 @@ namespace Rdf {
 		public bool get_literal_value_is_wf_xml ();
 		[CCode (cname = "librdf_node_get_literal_value_datatype_uri")]
 		public unowned Uri? get_literal_value_datatype_uri ();
+                [CCode (cname = "librdf_node_get_literal_gvalue")]
+                public GLib.Value get_literal_gvalue();
 
 		[CCode (cname = "librdf_node_get_li_ordinal")]
 		public int get_li_ordinal ();