|
@@ -1,6 +1,22 @@
|
|
#include "codec/codec_ttl.h"
|
|
#include "codec/codec_ttl.h"
|
|
|
|
|
|
|
|
|
|
|
|
+/** @brief NT codec iterator.
|
|
|
|
+ *
|
|
|
|
+ * This iterator yields one or more triples at a time, one group per subject,
|
|
|
|
+ * with the most compact form allowed by Turtle, e.g.
|
|
|
|
+ *
|
|
|
|
+ * :s :p1 :o1, :o2, o3; p2 o4, o5, <http://example.com/ext1> .
|
|
|
|
+ */
|
|
|
|
+typedef struct {
|
|
|
|
+ const LSUP_Codec * codec; ///< Codec that generated this iterator.
|
|
|
|
+ const LSUP_Graph *gr; ///< Graph being encoded.
|
|
|
|
+ LSUP_TermSet * subjects; ///< All subjects in the graph.
|
|
|
|
+ size_t s_cur; ///< Term set cursor.
|
|
|
|
+ LSUP_rc rc; ///< Internal return code.
|
|
|
|
+} LSUP_TTLCodecIterator;
|
|
|
|
+
|
|
|
|
+
|
|
/* * * Codec functions. * * */
|
|
/* * * Codec functions. * * */
|
|
|
|
|
|
static LSUP_rc
|
|
static LSUP_rc
|
|
@@ -61,7 +77,7 @@ term_to_ttl (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
|
|
return LSUP_ERROR;
|
|
return LSUP_ERROR;
|
|
buf_len = strlen (escaped) + 3; // Room for "" and terminator
|
|
buf_len = strlen (escaped) + 3; // Room for "" and terminator
|
|
|
|
|
|
- if (term->lang != 0) {
|
|
|
|
|
|
+ if (term->lang[0] != '\0') {
|
|
metadata = term->lang;
|
|
metadata = term->lang;
|
|
buf_len += strlen (metadata) + 1; // Room for @
|
|
buf_len += strlen (metadata) + 1; // Room for @
|
|
}
|
|
}
|
|
@@ -98,52 +114,143 @@ term_to_ttl (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static LSUP_CodecIterator *
|
|
|
|
-gr_to_ttl_init (const LSUP_Graph *gr);
|
|
|
|
|
|
+static void *
|
|
|
|
+gr_to_ttl_init (const LSUP_Graph *gr)
|
|
|
|
+{
|
|
|
|
+ LSUP_TTLCodecIterator *it;
|
|
|
|
+ MALLOC_GUARD (it, NULL);
|
|
|
|
+
|
|
|
|
+ it->codec = &ttl_codec;
|
|
|
|
+ it->gr = gr;
|
|
|
|
+ it->subjects = LSUP_graph_unique_terms (gr, TRP_POS_S);
|
|
|
|
+ // Sets the condition to build the prolog on 1st iteration.
|
|
|
|
+ it->rc = LSUP_NORESULT;
|
|
|
|
+
|
|
|
|
+ return it;
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
|
|
+/// Build header and prolog.
|
|
static LSUP_rc
|
|
static LSUP_rc
|
|
-gr_to_ttl_iter (LSUP_CodecIterator *it, unsigned char **res) {
|
|
|
|
- LSUP_rc rc = LSUP_graph_iter_next (it->gr_it, it->trp);
|
|
|
|
- if (rc != LSUP_OK) goto finally;
|
|
|
|
-
|
|
|
|
- term_to_ttl (it->trp->s, it->nsm, &it->str_s);
|
|
|
|
- term_to_ttl (it->trp->p, it->nsm, &it->str_p);
|
|
|
|
- term_to_ttl (it->trp->o, it->nsm, &it->str_o);
|
|
|
|
-
|
|
|
|
- // 3 term separators + dot + newline + terminal = 6
|
|
|
|
- unsigned char *tmp = realloc (
|
|
|
|
- *res, strlen (it->str_s) + strlen (it->str_p)
|
|
|
|
- + strlen (it->str_o) + 6);
|
|
|
|
|
|
+build_prolog (LSUP_TTLCodecIterator *it, char **res_p)
|
|
|
|
+{
|
|
|
|
+ char *res = fmt_header ("# ");
|
|
|
|
+
|
|
|
|
+ const char ***nsm = LSUP_nsmap_dump (LSUP_graph_namespace (it->gr));
|
|
|
|
+ const char *ns_tpl = "@prefix %s: <%s>\n";
|
|
|
|
+
|
|
|
|
+ // Prefix map.
|
|
|
|
+ for (size_t i = 0; nsm[i]; i++) {
|
|
|
|
+ const char **ns = nsm[i];
|
|
|
|
+ size_t old_len = strlen (res);
|
|
|
|
+ size_t ns_len = strlen (ns[0]) + strlen (ns[1]) + strlen (ns_tpl);
|
|
|
|
+ char *tmp = realloc (nsm, old_len + ns_len);
|
|
|
|
+ if (!UNLIKELY (!tmp)) return LSUP_MEM_ERR;
|
|
|
|
+
|
|
|
|
+ sprintf (res + old_len, ns_tpl, ns[0], ns[1]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Base.
|
|
|
|
+ char *base_uri_str;
|
|
|
|
+ LSUP_rc rc = LSUP_nsmap_denormalize_uri (
|
|
|
|
+ LSUP_graph_namespace (it->gr), LSUP_graph_uri (it->gr)->data,
|
|
|
|
+ &base_uri_str);
|
|
|
|
+ PRCCK (rc);
|
|
|
|
+ char *base_stmt_tpl = "\n@base <%s> .\n\n";
|
|
|
|
+ char *base_stmt = malloc (strlen (base_stmt_tpl) + strlen (base_uri_str));
|
|
|
|
+ if (!UNLIKELY (base_stmt)) return LSUP_MEM_ERR;
|
|
|
|
+ sprintf (base_stmt, base_stmt_tpl, base_uri_str);
|
|
|
|
+ res = realloc (res, strlen (res) + strlen (base_stmt));
|
|
|
|
+ if (!UNLIKELY (res)) return LSUP_MEM_ERR;
|
|
|
|
+ res = strcat (res, base_stmt);
|
|
|
|
+
|
|
|
|
+ *res_p = res;
|
|
|
|
+ it->rc = LSUP_OK;
|
|
|
|
+
|
|
|
|
+ return LSUP_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/// Encode all the triples for a single subject.
|
|
|
|
+static LSUP_rc
|
|
|
|
+gr_to_ttl_iter (void *h, char **res_p) {
|
|
|
|
+ LSUP_TTLCodecIterator *it = h;
|
|
|
|
+
|
|
|
|
+ if (it->rc == LSUP_NORESULT) return build_prolog (it, res_p);
|
|
|
|
+
|
|
|
|
+ LSUP_Term *s = NULL;
|
|
|
|
+ char *res = NULL; // Result string.
|
|
|
|
+ RCCK (LSUP_term_set_next (it->subjects, &it->s_cur, &s));
|
|
|
|
+
|
|
|
|
+ term_to_ttl (s, LSUP_graph_namespace (it->gr), &res);
|
|
|
|
+
|
|
|
|
+ LSUP_LinkMap *lmap = LSUP_graph_connections (
|
|
|
|
+ it->gr, s, LSUP_LINK_OUTBOUND);
|
|
|
|
+
|
|
|
|
+ LSUP_LinkMapIterator *lmit = LSUP_link_map_iter_new (lmap, s);
|
|
|
|
+ LSUP_Term *p = NULL;
|
|
|
|
+ char *p_str = NULL;
|
|
|
|
+ LSUP_TermSet *o_ts = NULL;
|
|
|
|
+ char *p_join = " ";
|
|
|
|
+ // Begin predicate loop.
|
|
|
|
+ while (LSUP_link_map_next (lmit, &p, &o_ts) != LSUP_END) {
|
|
|
|
+ // Add predicate representation.
|
|
|
|
+ RCCK (term_to_ttl (p, LSUP_graph_namespace (it->gr), &p_str));
|
|
|
|
+ char *tmp = realloc (
|
|
|
|
+ res, strlen (res) + strlen (p_str) + strlen (p_join) + 1);
|
|
|
|
+ if (UNLIKELY (!tmp)) {
|
|
|
|
+ it->rc = LSUP_MEM_ERR;
|
|
|
|
+ goto finally;
|
|
|
|
+ }
|
|
|
|
+ res = strcat (strcat (tmp, p_join), p_str);
|
|
|
|
+
|
|
|
|
+ free (p_str);
|
|
|
|
+ p_join = "; ";
|
|
|
|
+
|
|
|
|
+ // Add objects for predicate.
|
|
|
|
+ size_t i = 0;
|
|
|
|
+ LSUP_Term *o = NULL;
|
|
|
|
+ char *o_str = NULL;
|
|
|
|
+ char *o_join = " ";
|
|
|
|
+ while (LSUP_term_set_next (o_ts, &i, &o) != LSUP_END) {
|
|
|
|
+ it->rc = term_to_ttl (o, LSUP_graph_namespace (it->gr), &o_str);
|
|
|
|
+ RCCK (it->rc);
|
|
|
|
+ char *tmp = realloc (
|
|
|
|
+ res, strlen (res) + strlen (o_str) + strlen (o_join) + 1);
|
|
|
|
+ if (UNLIKELY (!tmp)) {
|
|
|
|
+ it->rc = LSUP_MEM_ERR;
|
|
|
|
+ goto finally;
|
|
|
|
+ }
|
|
|
|
+ res = strcat (strcat (tmp, o_join), o_str);
|
|
|
|
+
|
|
|
|
+ free (o_str);
|
|
|
|
+ o_join = ", ";
|
|
|
|
+ }
|
|
|
|
+ PRCCK (it->rc);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ char *s_sep = ".\n";
|
|
|
|
+ char *tmp = realloc (res, strlen (res) + strlen (s_sep) + 1);
|
|
if (UNLIKELY (!tmp)) {
|
|
if (UNLIKELY (!tmp)) {
|
|
- *res = NULL;
|
|
|
|
- rc = LSUP_MEM_ERR;
|
|
|
|
|
|
+ res = NULL;
|
|
|
|
+ it->rc = LSUP_MEM_ERR;
|
|
goto finally;
|
|
goto finally;
|
|
}
|
|
}
|
|
|
|
|
|
- sprintf ((char*)tmp, "%s %s %s .\n", it->str_s, it->str_p, it->str_o);
|
|
|
|
- *res = tmp;
|
|
|
|
-
|
|
|
|
- it->cur++;
|
|
|
|
|
|
+ *res_p = strcat (res, s_sep);
|
|
|
|
|
|
finally:
|
|
finally:
|
|
- LSUP_term_free (it->trp->s); it->trp->s = NULL;
|
|
|
|
- LSUP_term_free (it->trp->p); it->trp->p = NULL;
|
|
|
|
- LSUP_term_free (it->trp->o); it->trp->o = NULL;
|
|
|
|
|
|
+ LSUP_link_map_iter_free (lmit);
|
|
|
|
|
|
- return rc;
|
|
|
|
|
|
+ return it->rc;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
static void
|
|
-gr_to_ttl_done (LSUP_CodecIterator *it)
|
|
|
|
|
|
+gr_to_ttl_done (void *h)
|
|
{
|
|
{
|
|
- LSUP_graph_iter_free (it->gr_it);
|
|
|
|
- LSUP_triple_free (it->trp);
|
|
|
|
- free (it->rep);
|
|
|
|
- free (it->str_s);
|
|
|
|
- free (it->str_p);
|
|
|
|
- free (it->str_o);
|
|
|
|
|
|
+ LSUP_TTLCodecIterator *it = h;
|
|
|
|
+ LSUP_term_set_free (it->subjects);
|
|
free (it);
|
|
free (it);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -162,25 +269,3 @@ const LSUP_Codec ttl_codec = {
|
|
//.decode_term = LSUP_ttl_parse_term,
|
|
//.decode_term = LSUP_ttl_parse_term,
|
|
.decode_graph = LSUP_ttl_parse_doc,
|
|
.decode_graph = LSUP_ttl_parse_doc,
|
|
};
|
|
};
|
|
-
|
|
|
|
-
|
|
|
|
-/* * * Other static functions. * * */
|
|
|
|
-
|
|
|
|
-static LSUP_CodecIterator *
|
|
|
|
-gr_to_ttl_init (const LSUP_Graph *gr)
|
|
|
|
-{
|
|
|
|
- LSUP_CodecIterator *it;
|
|
|
|
- MALLOC_GUARD (it, NULL);
|
|
|
|
-
|
|
|
|
- it->codec = &ttl_codec;
|
|
|
|
- it->gr_it = LSUP_graph_lookup(gr, NULL, NULL, NULL, &it->cur);
|
|
|
|
- it->nsm = LSUP_graph_namespace (gr);
|
|
|
|
- it->cur = 0;
|
|
|
|
- it->trp = TRP_DUMMY;
|
|
|
|
- it->rep = NULL;
|
|
|
|
- it->str_s = NULL;
|
|
|
|
- it->str_p = NULL;
|
|
|
|
- it->str_o = NULL;
|
|
|
|
-
|
|
|
|
- return it;
|
|
|
|
-}
|
|
|