Volksdata 1.0b7
RDF library
Loading...
Searching...
No Matches
writer_ttl.c
Go to the documentation of this file.
2
3
4# define INDENT " "
5#define INDENT_L 4
6
18 const VOLK_Graph * gr;
19 void * txn;
21 size_t s_cur;
23 char * s_str;
24 char * p_str;
25 char * o_str;
26};
27
28
29/* * * Codec functions. * * */
30
32ttl_encode_term (const VOLK_Term *term, char **out_p)
33{
34 VOLK_rc rc;
35 char
36 *tmp = NULL,
37 *out = NULL,
38 *metadata = NULL;
39 size_t buf_len;
40
41 VOLK_rc md_rc = VOLK_NORESULT;
42 switch (term->type) {
44 if (strlen (term->data) == 0) {
45 // Empty URI.
46 NLRCCK (out = realloc (*out_p, 3), VOLK_MEM_ERR);
47 sprintf (out, "<>");
48 } else if (strcmp (term->data, VOLK_RDF_TYPE) == 0) {
49 // Shorten RDF type
50 buf_len = 2;
51 NLRCCK (out = realloc (*out_p, 2), VOLK_MEM_ERR);
52 out[0] = 'a';
53 out[1] = '\0';
54 } else {
55 md_rc = VOLK_nsmap_denormalize_uri (term->data, &tmp);
56 PRCCK (md_rc);
57 if (md_rc == VOLK_NORESULT) {
58 // If URI counld not be shortened, add `<>`
59 // and copy term from the original.
60 out = realloc (*out_p, strlen (term->data) + 3);
61 if (UNLIKELY (!out)) return VOLK_MEM_ERR;
62 sprintf (out, "<%s>", term->data);
63 } else {
64 // If URI was shortened, write it out without `<>` and
65 // use previously allocated data from denormalization.
66 // Free previous output pointer
67 free (*out_p);
68 out = tmp;
69 }
70 }
71 rc = VOLK_OK;
72 break;
73
75 // Calculate string length.
76 RCCK (escape_lit (term->data, &tmp));
77 buf_len = strlen (tmp) + 3; // Room for "" and terminator
78
79 // Data type.
80 bool shorten = false;
81 if (term->datatype && term->datatype != VOLK_default_datatype) {
82#define XSD "http://www.w3.org/2001/XMLSchema#"
83 // Shorten numeric and boolean types.
84 if (strcmp ( term->datatype->data, XSD "integer") == 0) {
85 // TODO check for valid format.
86 shorten = true;
87 } else if (strcmp ( term->datatype->data, XSD "double") == 0) {
88 // TODO check for valid format.
89 shorten = true;
90 } else if (strcmp ( term->datatype->data, XSD "decimal") == 0) {
91 // TODO check for valid format.
92 shorten = true;
93 } else if (strcmp ( term->datatype->data, XSD "boolean") == 0) {
94 // TODO check for valid format.
95 shorten = true;
96 } else {
98 term->datatype->data, &metadata);
99 PRCCK (md_rc);
100 // Room for `^^<>` for FQURI, `^^` for NS URI
101 if (md_rc == VOLK_NORESULT) {
102 buf_len += 4;
103 metadata = term->datatype->data;
104 } else {
105 buf_len += 2;
106 }
107 buf_len += strlen (metadata);
108 }
109#undef XSD
110 }
111
112 out = realloc (*out_p, buf_len);
113 NLRCCK (out, VOLK_MEM_ERR);
114
115 if (shorten) strcpy (out, tmp);
116 else if (metadata) {
117 char *fmt = (
118 md_rc == VOLK_NORESULT ? "\"%s\"^^<%s>"
119 : "\"%s\"^^%s");
120 sprintf (out, fmt, tmp, metadata);
121 // Ensure the term datatype is not freed at the end.
122 if (metadata == term->datatype->data) metadata = NULL;
123 }
124 else sprintf (out, "\"%s\"", tmp);
125
126 free (tmp);
127
128 rc = VOLK_OK;
129
130 break;
131
133 // Calculate string length.
134 if (escape_lit (term->data, &tmp) != VOLK_OK)
135 return VOLK_ERROR;
136 buf_len = strlen (tmp) + 3; // Room for "" and terminator
137
138 if (term->lang[0] != '\0') {
139 metadata = strndup (term->lang, sizeof (VOLK_LangTag));
140 buf_len += strlen (metadata) + 1; // Room for @
141 }
142
143 out = realloc (*out_p, buf_len);
144 if (UNLIKELY (!out)) return VOLK_MEM_ERR;
145
146 sprintf (out, "\"%s\"", tmp);
147 free (tmp);
148
149 // Add lang.
150 if (metadata) out = strcat (strcat (out, "@"), metadata);
151
152 rc = VOLK_OK;
153
154 break;
155
156 case VOLK_TERM_BNODE:
157 out = realloc (*out_p, strlen (term->data) + 3);
158 if (UNLIKELY (!out)) return VOLK_MEM_ERR;
159
160 sprintf (out, "_:%s", term->data);
161 rc = VOLK_OK;
162
163 break;
164
165 default:
166 out = *out_p; // This is considered garbage.
167 log_error ("Invalid term type: %d", term->type);
168 rc = VOLK_PARSE_ERR;
169 }
170 free (metadata);
171
172 *out_p = out;
173 return rc;
174}
175
176
177void *
178ttl_encode_graph_init (const VOLK_Graph *gr, void *oh)
179{
180 TTLEncodeOptions *options = oh;
181
182 TTLEncodeIterator *it;
183 CALLOC_GUARD (it, NULL);
184
185 it->flags = options ? options->flags : 0;
186 if (options && options->txn) {
187 it->txn = options->txn;
188 it->flags |= CODEC_EXT_TXN;
189 } else {
190 // Start a new transaction for the encoding loop if one is not provided.
191 VOLK_Store *store = VOLK_graph_store (gr);
193 VOLK_store_begin (store, VOLK_STORE_TXN_RO, &it->txn);
194 }
195 it->subjects = VOLK_graph_unique_terms_txn (it->txn, gr, TRP_POS_S);
196 it->gr = gr;
197 // Sets the condition to build the prolog on 1st iteration.
198 it->rc = VOLK_NORESULT;
199
200 return it;
201}
202
203
205static VOLK_rc
206ttl_build_prolog (TTLEncodeIterator *it, char **res_p)
207{
208 char *res = fmt_header ("# ");
209
210 const char ***nsm = VOLK_nsmap_dump ();
211 char *ns_tpl = "@prefix %s: <%s> .\n";
212
213 // Prefix map.
214 for (size_t i = 0; nsm[i]; i++) {
215 const char **ns = nsm[i];
216 size_t old_len = strlen (res);
217 size_t ns_len = strlen (ns[0]) + strlen (ns[1]) + strlen (ns_tpl);
218 char *tmp = realloc (res, old_len + ns_len + 1);
219 if (UNLIKELY (!tmp)) return VOLK_MEM_ERR;
220 res = tmp;
221
222 sprintf (res + old_len, ns_tpl, ns[0], ns[1]);
223 free (ns);
224 }
225 free (nsm);
226
227 // Base.
228 char *base_uri_str = VOLK_graph_uri (it->gr)->data;
229 char *base_stmt_tpl = "\n@base <%s> .\n\n";
230 char *base_stmt = malloc (
231 strlen (base_stmt_tpl) + strlen (base_uri_str) + 1);
232 if (!UNLIKELY (base_stmt)) return VOLK_MEM_ERR;
233 sprintf (base_stmt, base_stmt_tpl, base_uri_str);
234 res = realloc (res, strlen (res) + strlen (base_stmt) + 1);
235 if (!UNLIKELY (res)) return VOLK_MEM_ERR;
236 res = strcat (res, base_stmt);
237 free (base_stmt);
238
239 *res_p = res;
240 it->rc = VOLK_OK;
241
242 return VOLK_OK;
243}
244
245
252ttl_encode_graph_iter (void *h, char **res_p)
253{
254 TTLEncodeIterator *it = h;
255
256 if (!(it->flags & VOLK_CODEC_NO_PROLOG) && it->rc == VOLK_NORESULT)
257 return ttl_build_prolog (it, res_p);
258
259 VOLK_Term *s = NULL;
260 char *res = *res_p; // Result string will be reallocated.
261 VOLK_rc rc = VOLK_term_set_next (it->subjects, &it->s_cur, &s);
262 if (rc == VOLK_END) return rc; // Return without logging error.
263 RCCK (rc); // Log error or warning for anything else.
264
265 ttl_encode_term (s, &res);
266 if (it->flags & VOLK_CODEC_INDENT) {
267 // Indent encoded subject.
268 size_t indented_s_len = strlen (res) + INDENT_L + 1;
269 char *tmp = realloc (res, indented_s_len);
270 NLRCCK (tmp, VOLK_MEM_ERR);
271 // Shift characters by INDENT_L places.
272 for (int i = indented_s_len - INDENT_L - 1; i >= 0; i--) {
273 tmp[i + INDENT_L] = tmp[i];
274 if (i < INDENT_L) tmp[i] = ' ';
275 }
276 res = tmp;
277 }
278
280 it->txn, it->gr, s, VOLK_LINK_OUTBOUND);
281
282 VOLK_LinkMapIterator *lmit = VOLK_link_map_iter_new (lmap);
283 VOLK_Term *p = NULL;
284 VOLK_TermSet *o_ts = NULL;
285 char *p_join; // Newline & indent after subject.
286 if (it->flags & VOLK_CODEC_INDENT)
287 p_join = "\n" INDENT INDENT;
288 else
289 p_join = "\n" INDENT;
290 // Begin predicate loop.
291 while (VOLK_link_map_next (lmit, &p, &o_ts) != VOLK_END) {
292 // Add predicate representation.
293 RCCK (ttl_encode_term (p, &it->p_str));
294 char *tmp = realloc (
295 res, strlen (res) + strlen (it->p_str) + strlen (p_join) + 1);
296 NLCHECK (tmp, memfail);
297 res = strcat (strcat (tmp, p_join), it->p_str);
298
299 if (it->flags & VOLK_CODEC_INDENT)
300 p_join = " ;\n" INDENT INDENT;
301 else
302 p_join = " ;\n" INDENT;
303
304 // Add objects for predicate.
305 size_t i = 0;
306 VOLK_Term *o = NULL;
307 char *o_join = " ";
308 while (VOLK_term_set_next (o_ts, &i, &o) != VOLK_END) {
309 it->rc = ttl_encode_term (o, &it->o_str);
310 RCCK (it->rc);
311 char *tmp = realloc (
312 res, strlen (res) + strlen (it->o_str) + strlen (o_join) + 1
313 );
314 NLCHECK (tmp, memfail);
315 res = strcat (strcat (tmp, o_join), it->o_str);
316 if (it->flags & VOLK_CODEC_INDENT)
317 o_join = " ,\n" INDENT INDENT INDENT;
318 else
319 o_join = " ,\n" INDENT INDENT;
320 }
321 }
322
323 char *s_sep;
324 // Period goes on its own line for visibility.
325 if (it->flags & VOLK_CODEC_INDENT)
326 s_sep = "\n" INDENT ".\n\n";
327 else
328 s_sep = "\n.\n\n";
329 char *tmp = realloc (res, strlen (res) + strlen (s_sep) + 1);
330 NLCHECK (tmp, memfail);
331
332 *res_p = strcat (tmp, s_sep);
333
335 VOLK_link_map_free (lmap);
336
337 return it->rc;
338
339memfail:
340 free (res);
341 *res_p = NULL;
342 return VOLK_MEM_ERR;
343}
344
345
346void
348{
349 if (!h) return;
350 TTLEncodeIterator *it = h;
351 // Do not close transaction if it was externally provided.
352 if (it->txn && !(it->flags & CODEC_EXT_TXN))
353 VOLK_store_abort (VOLK_graph_store (it->gr), it->txn);
354 VOLK_term_set_free (it->subjects);
355 free (it->s_str);
356 free (it->p_str);
357 free (it->o_str);
358 free (it);
359}
#define UNLIKELY(x)
Definition core.h:39
@ TRP_POS_S
Definition buffer.h:20
char * fmt_header(char *pfx)
Format an informational header.
VOLK_CodecFlags
Parse error information.
VOLK_rc escape_lit(const char *in, char **out_p)
Add escape character (backslash) to illegal literal characters.
@ VOLK_CODEC_NO_PROLOG
Do not generate prolog.
@ CODEC_EXT_TXN
@ VOLK_CODEC_INDENT
VOLK_LinkMap * VOLK_graph_connections_txn(void *txn, const VOLK_Graph *gr, const VOLK_Term *t, const VOLK_LinkType type)
Get term pairs connected to a term in a graph.
Definition graph.c:705
VOLK_Store * VOLK_graph_store(const VOLK_Graph *gr)
Underlying graph store handle.
Definition graph.c:267
VOLK_TermSet * VOLK_graph_unique_terms_txn(void *txn, const VOLK_Graph *gr, VOLK_TriplePos pos)
Get all unique subjcts, predicates, or objects in a graph.
Definition graph.c:802
const VOLK_Term * VOLK_graph_uri(const VOLK_Graph *gr)
Read-only graph URI.
Definition graph.c:263
const char *** VOLK_nsmap_dump(void)
Dump all entries of the namespace map.
Definition namespace.c:191
VOLK_rc VOLK_nsmap_denormalize_uri(const char *fq_uri, char **pfx_uri_p)
Convert a FQ URI string to a prefixed string if the prefix is found.
Definition namespace.c:153
#define NLCHECK(exp, marker)
Log error and jump to marker if exp is NULL.
Definition core.h:314
#define CALLOC_GUARD(var, rc)
Allocate one pointer with calloc and return rc if it fails.
Definition core.h:388
char * strndup(const char *src, size_t max)
Replacement for GNU strndup.
Definition core.c:92
#define RCCK(exp)
Return exp return value if it is of VOLK_rc type and nonzero.
Definition core.h:322
#define NLRCCK(exp, _rc)
Return rc return code if exp is NULL.
Definition core.h:344
#define PRCCK(exp)
Return exp return value if it is of VOLK_rc type and negative (=error).
Definition core.h:333
#define VOLK_ERROR
Generic error return code.
Definition core.h:123
#define VOLK_MEM_ERR
Memory allocation error.
Definition core.h:144
#define VOLK_NORESULT
No result yielded.
Definition core.h:100
#define VOLK_END
Loop end.
Definition core.h:107
#define VOLK_OK
Generic success return code.
Definition core.h:83
#define VOLK_PARSE_ERR
Codec parser error.
Definition core.h:126
int VOLK_rc
Definition core.h:79
@ VOLK_STORE_TXN_RO
Start a read-only transaction.
@ VOLK_STORE_TXN
Supports transaction handling.
VOLK_StoreFeature VOLK_store_features(const VOLK_Store *store)
Feature flags belonging to the store interface.
Definition store.c:86
VOLK_rc VOLK_store_begin(VOLK_Store *store, VOLK_StoreFlags flags, void **txn)
Begin a transaction.
Definition store.c:96
void VOLK_store_abort(VOLK_Store *store, void *txn)
Abort (roll back) a transaction.
Definition store.c:115
struct hashmap VOLK_TermSet
a set of unique terms.
Definition term.h:124
VOLK_rc VOLK_term_set_next(VOLK_TermSet *ts, size_t *i, VOLK_Term **term)
Iterate trough a term set.
Definition term.c:592
void VOLK_link_map_iter_free(VOLK_LinkMapIterator *it)
Free a link map iterator.
Definition term.c:720
VOLK_LinkMapIterator * VOLK_link_map_iter_new(const VOLK_LinkMap *lmap)
Create a new iterator to loop through a link map.
Definition term.c:708
VOLK_Term * VOLK_default_datatype
Default literal data type URI.
Definition term.c:60
#define VOLK_RDF_TYPE
Definition term.h:17
void VOLK_term_set_free(VOLK_TermSet *ts)
Free a term set.
Definition term.c:604
VOLK_rc VOLK_link_map_next(VOLK_LinkMapIterator *it, VOLK_Term **lt, VOLK_TermSet **ts)
Iterate through a link map.
Definition term.c:724
void VOLK_link_map_free(VOLK_LinkMap *lm)
Free a link map.
Definition term.c:650
char VOLK_LangTag[8]
Language tag, currently restricted to 7 characters.
Definition term.h:28
@ VOLK_LINK_OUTBOUND
Outbound link (po).
Definition term.h:96
@ VOLK_TERM_IRIREF
IRI reference.
Definition term.h:35
@ VOLK_TERM_LT_LITERAL
Language-tagged string literal.
Definition term.h:37
@ VOLK_TERM_LITERAL
Literal without language tag.
Definition term.h:36
@ VOLK_TERM_BNODE
Blank node.
Definition term.h:38
VOLK_rc ttl_encode_term(const VOLK_Term *term, char **out_p)
Encode a single term as Turtle.
Definition writer_ttl.c:32
void ttl_encode_graph_done(void *h)
Finalize a TTL graph iteration.
Definition writer_ttl.c:347
VOLK_rc ttl_encode_graph_iter(void *h, char **res_p)
Run one encoding iteration.
Definition writer_ttl.c:252
void * ttl_encode_graph_init(const VOLK_Graph *gr, void *oh)
Initialize a TTL graph iteration.
Definition writer_ttl.c:178
Options passed to ttl_encode_graph_init().
Definition writer_ttl.h:15
void * txn
Transaction to use for encoding.
Definition writer_ttl.h:17
VOLK_CodecFlags flags
Iterator flags.
Definition writer_ttl.h:16
Store structure.
Definition store.h:59
RDF term.
Definition term.h:62
char * data
URI, literal value, or BNode label.
Definition term.h:63
struct term_t * datatype
Data type IRI for VOLK_TERM_LITERAL.
Definition term.h:65
VOLK_TermType type
Term type.
Definition term.h:70
VOLK_LangTag lang
Lang tag for VOLK_TERM_LT_LITERAL.
Definition term.h:66
TTL encoder iterator.
Definition writer_ttl.c:16
VOLK_TermSet * subjects
All subjects in the graph.
Definition writer_ttl.c:20
VOLK_rc rc
Internal return code.
Definition writer_ttl.c:22
const VOLK_Graph * gr
Graph being encoded.
Definition writer_ttl.c:18
char * s_str
Serialized subject block (output).
Definition writer_ttl.c:23
char * p_str
Serialized predicate block.
Definition writer_ttl.c:24
VOLK_CodecFlags flags
Iterator flags.
Definition writer_ttl.c:17
char * o_str
Serialized object block.
Definition writer_ttl.c:25
void * txn
Transaction to use.
Definition writer_ttl.c:19
size_t s_cur
Term set cursor.
Definition writer_ttl.c:21
#define XSD
#define INDENT
Definition writer_ttl.c:4
#define INDENT_L
Definition writer_ttl.c:5