Volksdata 1.0b7
RDF library
Loading...
Searching...
No Matches
writer_ttl.c
Go to the documentation of this file.
2
3
15 const VOLK_Graph * gr;
16 void * txn;
18 size_t s_cur;
20 char * s_str;
21 char * p_str;
22 char * o_str;
23};
24
25
26/* * * Codec functions. * * */
27
29ttl_encode_term (const VOLK_Term *term, char **out_p)
30{
31 VOLK_rc rc;
32 char
33 *tmp = NULL,
34 *out = NULL,
35 *metadata = NULL;
36 size_t buf_len;
37
38 VOLK_rc md_rc = VOLK_NORESULT;
39 switch (term->type) {
41 if (strlen (term->data) == 0) {
42 // Empty URI.
43 NLRCCK (out = realloc (*out_p, 3), VOLK_MEM_ERR);
44 sprintf (out, "<>");
45 } else if (strcmp (term->data, VOLK_RDF_TYPE) == 0) {
46 // Shorten RDF type
47 buf_len = 2;
48 NLRCCK (out = realloc (*out_p, 2), VOLK_MEM_ERR);
49 out[0] = 'a';
50 out[1] = '\0';
51 } else {
52 md_rc = VOLK_nsmap_denormalize_uri (term->data, &tmp);
53 PRCCK (md_rc);
54 if (md_rc == VOLK_NORESULT) {
55 // If URI counld not be shortened, add `<>`
56 // and copy term from the original.
57 out = realloc (*out_p, strlen (term->data) + 3);
58 if (UNLIKELY (!out)) return VOLK_MEM_ERR;
59 sprintf (out, "<%s>", term->data);
60 } else {
61 // If URI was shortened, write it out without `<>` and
62 // use previously allocated data from denormalization.
63 // Free previous output pointer
64 free (*out_p);
65 out = tmp;
66 }
67 }
68 rc = VOLK_OK;
69 break;
70
72 // Calculate string length.
73 RCCK (escape_lit (term->data, &tmp));
74 buf_len = strlen (tmp) + 3; // Room for "" and terminator
75
76 // Data type.
77 bool shorten = false;
78 if (term->datatype && term->datatype != VOLK_default_datatype) {
79#define XSD "http://www.w3.org/2001/XMLSchema#"
80 // Shorten numeric and boolean types.
81 if (strcmp ( term->datatype->data, XSD "integer") == 0) {
82 // TODO check for valid format.
83 shorten = true;
84 } else if (strcmp ( term->datatype->data, XSD "double") == 0) {
85 // TODO check for valid format.
86 shorten = true;
87 } else if (strcmp ( term->datatype->data, XSD "decimal") == 0) {
88 // TODO check for valid format.
89 shorten = true;
90 } else if (strcmp ( term->datatype->data, XSD "boolean") == 0) {
91 // TODO check for valid format.
92 shorten = true;
93 } else {
95 term->datatype->data, &metadata);
96 PRCCK (md_rc);
97 // Room for `^^<>` for FQURI, `^^` for NS URI
98 if (md_rc == VOLK_NORESULT) {
99 buf_len += 4;
100 metadata = term->datatype->data;
101 } else {
102 buf_len += 2;
103 }
104 buf_len += strlen (metadata);
105 }
106#undef XSD
107 }
108
109 out = realloc (*out_p, buf_len);
110 NLRCCK (out, VOLK_MEM_ERR);
111
112 if (shorten) strcpy (out, tmp);
113 else if (metadata) {
114 char *fmt = (
115 md_rc == VOLK_NORESULT ? "\"%s\"^^<%s>"
116 : "\"%s\"^^%s");
117 sprintf (out, fmt, tmp, metadata);
118 }
119 else sprintf (out, "\"%s\"", tmp);
120
121 free (tmp);
122
123 rc = VOLK_OK;
124
125 break;
126
128 // Calculate string length.
129 if (escape_lit (term->data, &tmp) != VOLK_OK)
130 return VOLK_ERROR;
131 buf_len = strlen (tmp) + 3; // Room for "" and terminator
132
133 if (term->lang[0] != '\0') {
134 metadata = strndup (term->lang, sizeof (VOLK_LangTag));
135 buf_len += strlen (metadata) + 1; // Room for @
136 }
137
138 out = realloc (*out_p, buf_len);
139 if (UNLIKELY (!out)) return VOLK_MEM_ERR;
140
141 sprintf (out, "\"%s\"", tmp);
142 free (tmp);
143
144 // Add lang.
145 if (metadata) out = strcat (strcat (out, "@"), metadata);
146
147 rc = VOLK_OK;
148
149 break;
150
151 case VOLK_TERM_BNODE:
152 out = realloc (*out_p, strlen (term->data) + 3);
153 if (UNLIKELY (!out)) return VOLK_MEM_ERR;
154
155 sprintf (out, "_:%s", term->data);
156 rc = VOLK_OK;
157
158 break;
159
160 default:
161 out = *out_p; // This is considered garbage.
162 log_error ("Invalid term type: %d", term->type);
163 rc = VOLK_PARSE_ERR;
164 }
165 if (metadata) free (metadata);
166
167 *out_p = out;
168 return rc;
169}
170
171
172void *
173ttl_encode_graph_init (const VOLK_Graph *gr, VOLK_CodecFlags flags)
174{
175 TTLEncodeIterator *it;
176 CALLOC_GUARD (it, NULL);
177
178 it->flags = flags;
179 it->gr = gr;
180 it->subjects = VOLK_graph_unique_terms (gr, TRP_POS_S);
181 // Sets the condition to build the prolog on 1st iteration.
182 it->rc = VOLK_NORESULT;
183 if (it->flags & VOLK_CODEC_TXN) {
184 VOLK_Store *store = VOLK_graph_store (gr);
186 VOLK_store_begin (store, VOLK_STORE_TXN_RO, &it->txn);
187 }
188
189 return it;
190}
191
192
194static VOLK_rc
195ttl_build_prolog (TTLEncodeIterator *it, char **res_p)
196{
197 char *res = fmt_header ("# ");
198
199 const char ***nsm = VOLK_nsmap_dump ();
200 char *ns_tpl = "@prefix %s: <%s> .\n";
201
202 // Prefix map.
203 for (size_t i = 0; nsm[i]; i++) {
204 const char **ns = nsm[i];
205 size_t old_len = strlen (res);
206 size_t ns_len = strlen (ns[0]) + strlen (ns[1]) + strlen (ns_tpl);
207 char *tmp = realloc (res, old_len + ns_len + 1);
208 if (UNLIKELY (!tmp)) return VOLK_MEM_ERR;
209 res = tmp;
210
211 sprintf (res + old_len, ns_tpl, ns[0], ns[1]);
212 free (ns);
213 }
214 free (nsm);
215
216 // Base.
217 char *base_uri_str = VOLK_graph_uri (it->gr)->data;
218 char *base_stmt_tpl = "\n@base <%s> .\n\n";
219 char *base_stmt = malloc (
220 strlen (base_stmt_tpl) + strlen (base_uri_str) + 1);
221 if (!UNLIKELY (base_stmt)) return VOLK_MEM_ERR;
222 sprintf (base_stmt, base_stmt_tpl, base_uri_str);
223 res = realloc (res, strlen (res) + strlen (base_stmt) + 1);
224 if (!UNLIKELY (res)) return VOLK_MEM_ERR;
225 res = strcat (res, base_stmt);
226 free (base_stmt);
227
228 *res_p = res;
229 it->rc = VOLK_OK;
230
231 return VOLK_OK;
232}
233
234
236ttl_encode_graph_iter (void *h, char **res_p)
237{
238 TTLEncodeIterator *it = h;
239
240 if (!(it->flags & VOLK_CODEC_NO_PROLOG) && it->rc == VOLK_NORESULT)
241 return ttl_build_prolog (it, res_p);
242
243 VOLK_Term *s = NULL;
244 char *res = *res_p; // Result string will be reallocated.
245 VOLK_rc rc = VOLK_term_set_next (it->subjects, &it->s_cur, &s);
246 if (rc == VOLK_END) return rc; // Return without logging error.
247 RCCK (rc); // Log error or warning for anything else.
248
249 ttl_encode_term (s, &res);
250
252 it->gr, s, VOLK_LINK_OUTBOUND);
253
254 VOLK_LinkMapIterator *lmit = VOLK_link_map_iter_new (lmap);
255 VOLK_Term *p = NULL;
256 VOLK_TermSet *o_ts = NULL;
257 char *p_join = "\n "; // Newline & indent after subject.
258 // Begin predicate loop.
259 while (VOLK_link_map_next (lmit, &p, &o_ts) != VOLK_END) {
260 // Add predicate representation.
261 RCCK (ttl_encode_term (p, &it->p_str));
262 char *tmp = realloc (
263 res, strlen (res) + strlen (it->p_str) + strlen (p_join) + 1);
264 if (UNLIKELY (!tmp)) goto memfail;
265 res = strcat (strcat (tmp, p_join), it->p_str);
266
267 p_join = " ;\n ";
268
269 // Add objects for predicate.
270 size_t i = 0;
271 VOLK_Term *o = NULL;
272 char *o_join = " ";
273 while (VOLK_term_set_next (o_ts, &i, &o) != VOLK_END) {
274 it->rc = ttl_encode_term (o, &it->o_str);
275 RCCK (it->rc);
276 char *tmp = realloc (
277 res, strlen (res) + strlen (it->o_str) + strlen (o_join) + 1);
278 if (UNLIKELY (!tmp)) goto memfail;
279 res = strcat (strcat (tmp, o_join), it->o_str);
280 o_join = " ,\n "; // Double indent for objects.
281 }
282 }
283
284 char *s_sep = "\n.\n\n"; // Period goes on its own line for visibility.
285 char *tmp = realloc (res, strlen (res) + strlen (s_sep) + 1);
286 if (UNLIKELY (!tmp)) goto memfail;
287
288 *res_p = strcat (tmp, s_sep);
289
291 VOLK_link_map_free (lmap);
292
293 return it->rc;
294
295memfail:
296 free (res);
297 *res_p = NULL;
298 return VOLK_MEM_ERR;
299}
300
301
302void
304{
305 if (!h) return;
306 TTLEncodeIterator *it = h;
307 if (it->txn) VOLK_store_abort (VOLK_graph_store (it->gr), it->txn);
308 VOLK_term_set_free (it->subjects);
309 free (it->s_str);
310 free (it->p_str);
311 free (it->o_str);
312 free (it);
313}
#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.
@ VOLK_CODEC_TXN
VOLK_LinkMap * VOLK_graph_connections(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:704
VOLK_TermSet * VOLK_graph_unique_terms(const VOLK_Graph *gr, VOLK_TriplePos pos)
Get all unique subjcts, predicates, or objects in a graph.
Definition graph.c:798
VOLK_Store * VOLK_graph_store(const VOLK_Graph *gr)
Underlying graph store handle.
Definition graph.c:267
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 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
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:13
VOLK_TermSet * subjects
All subjects in the graph.
Definition writer_ttl.c:17
VOLK_rc rc
Internal return code.
Definition writer_ttl.c:19
const VOLK_Graph * gr
Graph being encoded.
Definition writer_ttl.c:15
char * s_str
Serialized subject block (output).
Definition writer_ttl.c:20
char * p_str
Serialized predicate block.
Definition writer_ttl.c:21
VOLK_CodecFlags flags
Iterator flags.
Definition writer_ttl.c:14
char * o_str
Serialized object block.
Definition writer_ttl.c:22
void * txn
Transaction to use.
Definition writer_ttl.c:16
size_t s_cur
Term set cursor.
Definition writer_ttl.c:18
VOLK_rc ttl_encode_term(const VOLK_Term *term, char **out_p)
Definition writer_ttl.c:29
#define XSD
void ttl_encode_graph_done(void *h)
Definition writer_ttl.c:303
VOLK_rc ttl_encode_graph_iter(void *h, char **res_p)
Definition writer_ttl.c:236
void * ttl_encode_graph_init(const VOLK_Graph *gr, VOLK_CodecFlags flags)
Definition writer_ttl.c:173