glibrdf

GLib wrapper for the Redland RDF library
git clone https://code.djc.id.au/git/glibrdf/

glibrdf.c (3764B) - raw

      1 
      2 /*
      3  * glibrdf.c
      4  * Copyright 2012 Dan Callaghan <djc@djc.id.au>
      5  * Licensed under GPLv3
      6  */
      7 
      8 #include <stdbool.h>
      9 #include <time.h>
     10 #include "glibrdf.h"
     11 
     12 GType librdf_node_get_gtype(void) {
     13     static volatile gsize _librdf_node_type_id = 0;
     14     if (g_once_init_enter(&_librdf_node_type_id)) {
     15         GType type_id = g_boxed_type_register_static("librdf_node",
     16                 (GBoxedCopyFunc) librdf_new_node_from_node,
     17                 (GBoxedFreeFunc) librdf_free_node);
     18         g_once_init_leave(&_librdf_node_type_id, type_id);
     19     }
     20     return _librdf_node_type_id;
     21 }
     22 
     23 // glib should do this for me >:(
     24 static GDate *parse_iso8601_date(const gchar *s) {
     25     struct tm tm = {0};
     26     if (*strptime(s, "%F", &tm) != '\0')
     27         return NULL;
     28     return g_date_new_dmy(tm.tm_mday, 1 + tm.tm_mon, 1900 + tm.tm_year);
     29 }
     30 
     31 // g_time_val_from_iso8601 doesn't preserve timezone >:(((
     32 static GDateTime *parse_iso8601_datetime(const gchar *s) {
     33     struct tm tm = {0};
     34     // parse the date and time, timezone will be left at the end
     35     const gchar *rest = strptime(s, "%FT%T", &tm);
     36     GTimeZone *tz = g_time_zone_new(rest);
     37     g_return_val_if_fail(tz != NULL, NULL);
     38     GDateTime *result = g_date_time_new(tz,
     39             1900 + tm.tm_year,
     40             1 + tm.tm_mon,
     41             tm.tm_mday,
     42             tm.tm_hour,
     43             tm.tm_min,
     44             (gdouble) tm.tm_sec);
     45     g_time_zone_unref(tz);
     46     return result;
     47 }
     48 
     49 // XXX handle parse failures more gracefully?
     50 
     51 static void integer(const gchar *lv, GValue *value_out) {
     52     g_value_init(value_out, G_TYPE_INT64);
     53     gchar *lv_unconsumed;
     54     g_value_set_int64(value_out, g_ascii_strtoll(lv, &lv_unconsumed, 10));
     55     g_return_if_fail(*lv_unconsumed == '\0');
     56     return;
     57 }
     58 
     59 static void date(const gchar *lv, GValue *value_out) {
     60     GDate *date = parse_iso8601_date(lv);
     61     g_return_if_fail(date != NULL);
     62     g_value_init(value_out, G_TYPE_DATE);
     63     g_value_take_boxed(value_out, date);
     64     return;
     65 }
     66 
     67 static void datetime(const gchar *lv, GValue *value_out) {
     68     GDateTime *datetime = parse_iso8601_datetime(lv);
     69     g_return_if_fail(datetime != NULL);
     70     g_value_init(value_out, G_TYPE_DATE_TIME);
     71     g_value_take_boxed(value_out, datetime);
     72     return;
     73 }
     74 
     75 librdf_gvalue_adaptor_func librdf_default_gvalue_adaptor_map(librdf_uri *datatype_uri) {
     76     const gchar *datatype_uri_string =
     77         (const gchar *)librdf_uri_as_string(datatype_uri);
     78     if (g_strcmp0(datatype_uri_string,
     79             "http://www.w3.org/2001/XMLSchema#integer") == 0)
     80         return integer;
     81     if (g_strcmp0(datatype_uri_string,
     82             "http://www.w3.org/TR/xmlschema-2/#date") == 0)
     83         return date;
     84     if (g_strcmp0(datatype_uri_string,
     85             "http://www.w3.org/TR/xmlschema-2/#datetime") == 0)
     86         return datetime;
     87     return NULL;
     88 }
     89 
     90 void librdf_node_get_literal_gvalue(librdf_node *node,
     91         librdf_gvalue_adaptor_map_func adaptor_map, GValue *value_out) {
     92     g_return_if_fail(librdf_node_is_literal(node));
     93     const gchar *lv = (const gchar *)librdf_node_get_literal_value(node);
     94     g_return_if_fail(lv != NULL);
     95     librdf_uri *datatype_uri = librdf_node_get_literal_value_datatype_uri(node);
     96     if (datatype_uri == NULL) {
     97         g_value_init(value_out, G_TYPE_STRING);
     98         g_value_set_string(value_out, lv);
     99         return;
    100     }
    101     if (adaptor_map == NULL)
    102         adaptor_map = librdf_default_gvalue_adaptor_map;
    103     librdf_gvalue_adaptor_func adaptor = adaptor_map(datatype_uri);
    104     if (adaptor == NULL) {
    105         g_warning("Unhandled RDF type %s", librdf_uri_as_string(datatype_uri));
    106         g_value_init(value_out, G_TYPE_STRING);
    107         g_value_set_string(value_out, lv);
    108     }
    109     adaptor(lv, value_out);
    110     g_return_if_fail(G_IS_VALUE(value_out));
    111     return;
    112 }