1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * raptor_turtle_writer.c - Raptor Turtle Writer
4 *
5 * Copyright (C) 2006, Dave Robillard
6 * Copyright (C) 2003-2008, David Beckett http://www.dajobe.org/
7 * Copyright (C) 2003-2005, University of Bristol, UK http://www.bristol.ac.uk/
8 *
9 * This package is Free Software and part of Redland http://librdf.org/
10 *
11 * It is licensed under the following three licenses as alternatives:
12 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
13 * 2. GNU General Public License (GPL) V2 or any newer version
14 * 3. Apache License, V2.0 or any newer version
15 *
16 * You may not use this file except in compliance with at least one of
17 * the above three licenses.
18 *
19 * See LICENSE.html or LICENSE.txt at the top of this package for the
20 * complete terms and further detail along with the license texts for
21 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
22 *
23 *
24 */
25
26
27 #ifdef HAVE_CONFIG_H
28 #include <raptor_config.h>
29 #endif
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <stdarg.h>
35 #ifdef HAVE_ERRNO_H
36 #include <errno.h>
37 #endif
38 #ifdef HAVE_STDLIB_H
39 #include <stdlib.h>
40 #endif
41 #ifdef HAVE_LIMITS_H
42 #include <limits.h>
43 #endif
44 #include <math.h>
45
46 /* Raptor includes */
47 #include "raptor2.h"
48 #include "raptor_internal.h"
49
50 #ifndef STANDALONE
51
52
53 typedef enum {
54 TURTLE_WRITER_AUTO_INDENT = 1
55 } raptor_turtle_writer_flags;
56
57
58 #define TURTLE_WRITER_AUTO_INDENT(turtle_writer) ((turtle_writer->flags & TURTLE_WRITER_AUTO_INDENT) != 0)
59
60 struct raptor_turtle_writer_s {
61 raptor_world* world;
62
63 int depth;
64
65 raptor_uri* base_uri;
66
67 int my_nstack;
68 raptor_namespace_stack *nstack;
69 int nstack_depth;
70
71 /* outputting to this iostream */
72 raptor_iostream *iostr;
73
74 /* Turtle Writer flags - bits defined in enum raptor_turtle_writer_flags */
75 int flags;
76
77 /* indentation per level if formatting */
78 int indent;
79 };
80
81
82 /* 16 spaces */
83 #define SPACES_BUFFER_SIZE sizeof(spaces_buffer)
84 static const unsigned char spaces_buffer[] = {
85 ' ', ' ', ' ', ' ',
86 ' ', ' ', ' ', ' ',
87 ' ', ' ', ' ', ' ',
88 ' ', ' ', ' ', ' '
89 };
90
91
92 void
raptor_turtle_writer_increase_indent(raptor_turtle_writer * turtle_writer)93 raptor_turtle_writer_increase_indent(raptor_turtle_writer *turtle_writer)
94 {
95 turtle_writer->depth += turtle_writer->indent;
96 }
97
98
99 void
raptor_turtle_writer_decrease_indent(raptor_turtle_writer * turtle_writer)100 raptor_turtle_writer_decrease_indent(raptor_turtle_writer *turtle_writer)
101 {
102 turtle_writer->depth -= turtle_writer->indent;
103 }
104
105
106 void
raptor_turtle_writer_newline(raptor_turtle_writer * turtle_writer)107 raptor_turtle_writer_newline(raptor_turtle_writer *turtle_writer)
108 {
109 int num_spaces;
110
111 raptor_iostream_write_byte('\n', turtle_writer->iostr);
112
113 if(!TURTLE_WRITER_AUTO_INDENT(turtle_writer))
114 return;
115
116 num_spaces = turtle_writer->depth * turtle_writer->indent;
117
118 while(num_spaces > 0) {
119 int count;
120 count = (num_spaces > RAPTOR_GOOD_CAST(int, SPACES_BUFFER_SIZE)) ?
121 RAPTOR_GOOD_CAST(int, SPACES_BUFFER_SIZE) : num_spaces;
122
123 raptor_iostream_counted_string_write(spaces_buffer, count, turtle_writer->iostr);
124
125 num_spaces -= count;
126 }
127
128 return;
129 }
130
131
132 /**
133 * raptor_new_turtle_writer:
134 * @world: raptor_world object
135 * @base_uri: Base URI for the writer (or NULL)
136 * @write_base_uri: non-0 to write '@base' directive to output
137 * @nstack: Namespace stack for the writer to start with (or NULL)
138 * @iostr: I/O stream to write to
139 *
140 * Constructor - Create a new Turtle Writer writing Turtle to a raptor_iostream
141 *
142 * Return value: a new #raptor_turtle_writer object or NULL on failure
143 **/
144 raptor_turtle_writer*
raptor_new_turtle_writer(raptor_world * world,raptor_uri * base_uri,int write_base_uri,raptor_namespace_stack * nstack,raptor_iostream * iostr)145 raptor_new_turtle_writer(raptor_world* world,
146 raptor_uri* base_uri, int write_base_uri,
147 raptor_namespace_stack *nstack,
148 raptor_iostream* iostr)
149 {
150 raptor_turtle_writer* turtle_writer;
151
152 RAPTOR_CHECK_CONSTRUCTOR_WORLD(world);
153
154 if(!nstack || !iostr)
155 return NULL;
156
157 raptor_world_open(world);
158
159 turtle_writer = RAPTOR_CALLOC(raptor_turtle_writer*, 1,
160 sizeof(*turtle_writer));
161
162 if(!turtle_writer)
163 return NULL;
164
165 turtle_writer->world = world;
166
167 turtle_writer->nstack_depth = 0;
168
169 turtle_writer->nstack = nstack;
170 if(!turtle_writer->nstack) {
171 turtle_writer->nstack = raptor_new_namespaces(world, 1);
172 turtle_writer->my_nstack = 1;
173 }
174
175 turtle_writer->iostr = iostr;
176
177 turtle_writer->flags = 0;
178 turtle_writer->indent = 2;
179
180 turtle_writer->base_uri = NULL;
181 /* Ensure any initial base URI is not written relative */
182 if(base_uri && write_base_uri)
183 raptor_turtle_writer_base(turtle_writer, base_uri);
184 turtle_writer->base_uri = base_uri;
185
186 return turtle_writer;
187 }
188
189
190 /**
191 * raptor_free_turtle_writer:
192 * @turtle_writer: Turtle writer object
193 *
194 * Destructor - Free Turtle Writer
195 *
196 **/
197 void
raptor_free_turtle_writer(raptor_turtle_writer * turtle_writer)198 raptor_free_turtle_writer(raptor_turtle_writer* turtle_writer)
199 {
200 if(!turtle_writer)
201 return;
202
203 if(turtle_writer->nstack && turtle_writer->my_nstack)
204 raptor_free_namespaces(turtle_writer->nstack);
205
206 RAPTOR_FREE(raptor_turtle_writer, turtle_writer);
207 }
208
209
210 static int
raptor_turtle_writer_contains_newline(const unsigned char * s,size_t len)211 raptor_turtle_writer_contains_newline(const unsigned char *s, size_t len)
212 {
213 size_t i = 0;
214
215 for( ; i < len; i++)
216 if(s[i] == '\n')
217 return 1;
218
219 return 0;
220 }
221
222
223 /**
224 * raptor_turtle_writer_raw:
225 * @turtle_writer: Turtle writer object
226 * @s: raw string to write
227 *
228 * Write a raw string to the Turtle writer verbatim.
229 *
230 **/
231 void
raptor_turtle_writer_raw(raptor_turtle_writer * turtle_writer,const unsigned char * s)232 raptor_turtle_writer_raw(raptor_turtle_writer* turtle_writer,
233 const unsigned char *s)
234 {
235 raptor_iostream_string_write(s, turtle_writer->iostr);
236 }
237
238
239 /**
240 * raptor_turtle_writer_raw_counted:
241 * @turtle_writer: Turtle writer object
242 * @s: raw string to write
243 * @len: length of string
244 *
245 * Write a counted string to the Turtle writer verbatim.
246 *
247 **/
248 void
raptor_turtle_writer_raw_counted(raptor_turtle_writer * turtle_writer,const unsigned char * s,unsigned int len)249 raptor_turtle_writer_raw_counted(raptor_turtle_writer* turtle_writer,
250 const unsigned char *s, unsigned int len)
251 {
252 raptor_iostream_counted_string_write(s, len, turtle_writer->iostr);
253 }
254
255
256 /**
257 * raptor_turtle_writer_namespace_prefix:
258 * @turtle_writer: Turtle writer object
259 * @ns: Namespace to write prefix declaration for
260 *
261 * Write a namespace prefix declaration (@prefix)
262 *
263 * Must only be used at the beginning of a document.
264 */
265 void
raptor_turtle_writer_namespace_prefix(raptor_turtle_writer * turtle_writer,raptor_namespace * ns)266 raptor_turtle_writer_namespace_prefix(raptor_turtle_writer* turtle_writer,
267 raptor_namespace* ns)
268 {
269 raptor_iostream_string_write("@prefix ", turtle_writer->iostr);
270 if(ns->prefix)
271 raptor_iostream_string_write(raptor_namespace_get_prefix(ns),
272 turtle_writer->iostr);
273 raptor_iostream_counted_string_write(": ", 2, turtle_writer->iostr);
274 raptor_turtle_writer_reference(turtle_writer, raptor_namespace_get_uri(ns));
275 raptor_iostream_counted_string_write(" .\n", 3, turtle_writer->iostr);
276 }
277
278
279 /**
280 * raptor_turtle_writer_base:
281 * @turtle_writer: Turtle writer object
282 * @base_uri: New base URI or NULL
283 *
284 * Write a base URI directive (@base) to set the in-scope base URI
285 */
286 void
raptor_turtle_writer_base(raptor_turtle_writer * turtle_writer,raptor_uri * base_uri)287 raptor_turtle_writer_base(raptor_turtle_writer* turtle_writer,
288 raptor_uri* base_uri)
289 {
290 if(base_uri) {
291 raptor_iostream_counted_string_write("@base ", 6, turtle_writer->iostr);
292 raptor_turtle_writer_reference(turtle_writer, base_uri);
293 raptor_iostream_counted_string_write(" .\n", 3, turtle_writer->iostr);
294 }
295 }
296
297
298 /**
299 * raptor_turtle_writer_reference:
300 * @turtle_writer: Turtle writer object
301 * @uri: URI to write
302 *
303 * Write a Turtle-encoded URI to the Turtle writer.
304 *
305 * Return value: non-0 on failure
306 **/
307 int
raptor_turtle_writer_reference(raptor_turtle_writer * turtle_writer,raptor_uri * uri)308 raptor_turtle_writer_reference(raptor_turtle_writer* turtle_writer,
309 raptor_uri* uri)
310 {
311 return raptor_uri_escaped_write(uri, turtle_writer->base_uri,
312 RAPTOR_ESCAPED_WRITE_TURTLE_URI,
313 turtle_writer->iostr);
314 }
315
316
317 /**
318 * raptor_turtle_writer_qname:
319 * @turtle_writer: Turtle writer object
320 * @qname: qname to write
321 *
322 * Write a QName to the Turtle writer.
323 *
324 **/
325 void
raptor_turtle_writer_qname(raptor_turtle_writer * turtle_writer,raptor_qname * qname)326 raptor_turtle_writer_qname(raptor_turtle_writer* turtle_writer,
327 raptor_qname* qname)
328 {
329 raptor_iostream* iostr = turtle_writer->iostr;
330
331 if(qname->nspace && qname->nspace->prefix_length > 0)
332 raptor_iostream_counted_string_write(qname->nspace->prefix,
333 qname->nspace->prefix_length,
334 iostr);
335 raptor_iostream_write_byte(':', iostr);
336
337 raptor_iostream_counted_string_write(qname->local_name,
338 qname->local_name_length,
339 iostr);
340 return;
341 }
342
343
344 /**
345 * raptor_turtle_writer_quoted_counted_string:
346 * @turtle_writer: Turtle writer object
347 * @s: string to write
348 * @len: string length
349 *
350 * Write a Turtle escaped-string inside double quotes to the writer.
351 *
352 * Return value: non-0 on failure
353 **/
354 int
raptor_turtle_writer_quoted_counted_string(raptor_turtle_writer * turtle_writer,const unsigned char * s,size_t len)355 raptor_turtle_writer_quoted_counted_string(raptor_turtle_writer* turtle_writer,
356 const unsigned char *s, size_t len)
357 {
358 const unsigned char *quotes = (const unsigned char *)"\"\"\"\"";
359 const unsigned char *q = quotes + 2;
360 size_t q_len = 1;
361 int flags = RAPTOR_ESCAPED_WRITE_TURTLE_LITERAL;
362 int rc = 0;
363
364 if(!s)
365 return 1;
366
367 /* Turtle """longstring""" (2) or "string" (1) */
368 if(raptor_turtle_writer_contains_newline(s, len)) {
369 /* long string */
370 flags = RAPTOR_ESCAPED_WRITE_TURTLE_LONG_LITERAL;
371 q = quotes;
372 q_len = 3;
373 }
374
375 raptor_iostream_counted_string_write(q, q_len, turtle_writer->iostr);
376 rc = raptor_string_escaped_write(s, len, '"',
377 flags, turtle_writer->iostr);
378 raptor_iostream_counted_string_write(q, q_len, turtle_writer->iostr);
379
380 return rc;
381 }
382
383
384 /*
385 * raptor_turtle_writer_literal:
386 * @turtle_writer: Turtle writer object
387 * @nstack: Namespace stack for making a QName for datatype URI
388 * @s: literal string to write (SHARED)
389 * @lang: language tag (may be NULL)
390 * @datatype: datatype URI (may be NULL)
391 *
392 * INTERNAL - Write a literal (possibly with lang and datatype) to the Turtle writer.
393 *
394 * Return value: non-0 on failure
395 **/
396 int
raptor_turtle_writer_literal(raptor_turtle_writer * turtle_writer,raptor_namespace_stack * nstack,const unsigned char * s,const unsigned char * lang,raptor_uri * datatype)397 raptor_turtle_writer_literal(raptor_turtle_writer* turtle_writer,
398 raptor_namespace_stack *nstack,
399 const unsigned char* s, const unsigned char* lang,
400 raptor_uri* datatype)
401 {
402 /* DBL_MAX = 309 decimal digits */
403 #define INT_MAX_LEN 309
404
405 /* DBL_EPSILON = 52 digits */
406 #define FRAC_MAX_LEN 52
407
408 char* endptr = (char *)s;
409 int written = 0;
410
411 /* typed literal special cases */
412 if(datatype) {
413 /* integer */
414 if(raptor_uri_equals(datatype, turtle_writer->world->xsd_integer_uri)) {
415 /* FIXME. Work around that gcc < 4.5 cannot disable warn_unused_result */
416 long gcc_is_stupid = strtol((const char*)s, &endptr, 10);
417 if(endptr != (char*)s && !*endptr) {
418 raptor_iostream_string_write(s, turtle_writer->iostr);
419 /* More gcc madness to 'use' the variable I didn't want */
420 written = 1 + 0 * (int)gcc_is_stupid;
421 } else {
422 raptor_log_error(turtle_writer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
423 "Illegal value for xsd:integer literal.");
424 }
425
426 /* double, decimal */
427 } else if(raptor_uri_equals(datatype, turtle_writer->world->xsd_double_uri) ||
428 raptor_uri_equals(datatype, turtle_writer->world->xsd_decimal_uri)) {
429 /* FIXME. Work around that gcc < 4.5 cannot disable warn_unused_result */
430 double gcc_is_doubly_stupid = strtod((const char*)s, &endptr);
431 if(endptr != (char*)s && !*endptr) {
432 raptor_iostream_string_write(s, turtle_writer->iostr);
433 /* More gcc madness to 'use' the variable I didn't want */
434 written = 1 + 0 * (int)gcc_is_doubly_stupid;
435 } else {
436 raptor_log_error(turtle_writer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
437 "Illegal value for xsd:double or xsd:decimal literal.");
438 }
439
440 /* boolean */
441 } else if(raptor_uri_equals(datatype, turtle_writer->world->xsd_boolean_uri)) {
442 if(!strcmp((const char*)s, "0") || !strcmp((const char*)s, "false")) {
443 raptor_iostream_string_write("false", turtle_writer->iostr);
444 written = 1;
445 } else if(!strcmp((const char*)s, "1") || !strcmp((const char*)s, "true")) {
446 raptor_iostream_string_write("true", turtle_writer->iostr);
447 written = 1;
448 } else {
449 raptor_log_error(turtle_writer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
450 "Illegal value for xsd:boolean literal.");
451 }
452 }
453 }
454
455 if(written)
456 return 0;
457
458 if(raptor_turtle_writer_quoted_counted_string(turtle_writer, s,
459 strlen((const char*)s)))
460 return 1;
461
462 /* typed literal, not a special case */
463 if(datatype) {
464 raptor_qname* qname;
465
466 raptor_iostream_string_write("^^", turtle_writer->iostr);
467 qname = raptor_new_qname_from_namespace_uri(nstack, datatype, 10);
468 if(qname) {
469 raptor_turtle_writer_qname(turtle_writer, qname);
470 raptor_free_qname(qname);
471 } else
472 raptor_turtle_writer_reference(turtle_writer, datatype);
473 } else if(lang) {
474 /* literal with language tag */
475 raptor_iostream_write_byte('@', turtle_writer->iostr);
476 raptor_iostream_string_write(lang, turtle_writer->iostr);
477 }
478
479 return 0;
480 }
481
482
483 /**
484 * raptor_turtle_writer_comment:
485 * @turtle_writer: Turtle writer object
486 * @s: comment string to write
487 *
488 * Write a Turtle comment to the Turtle writer.
489 *
490 **/
491 void
raptor_turtle_writer_comment(raptor_turtle_writer * turtle_writer,const unsigned char * string)492 raptor_turtle_writer_comment(raptor_turtle_writer* turtle_writer,
493 const unsigned char *string)
494 {
495 unsigned char c;
496 size_t len = strlen((const char*)string);
497
498 raptor_iostream_counted_string_write((const unsigned char*)"# ", 2,
499 turtle_writer->iostr);
500
501 for(; (c=*string); string++, len--) {
502 if(c == '\n') {
503 raptor_turtle_writer_newline(turtle_writer);
504 raptor_iostream_counted_string_write((const unsigned char*)"# ", 2,
505 turtle_writer->iostr);
506 } else if(c != '\r') {
507 /* skip carriage returns (windows... *sigh*) */
508 raptor_iostream_write_byte(c, turtle_writer->iostr);
509 }
510 }
511
512 raptor_turtle_writer_newline(turtle_writer);
513 }
514
515
516 /**
517 * raptor_turtle_writer_set_option:
518 * @turtle_writer: #raptor_turtle_writer turtle_writer object
519 * @option: option to set from enumerated #raptor_option values
520 * @value: integer option value (0 or larger)
521 *
522 * Set turtle_writer options with integer values.
523 *
524 * The allowed options are available via
525 * raptor_world_get_option_description()
526 *
527 * Return value: non 0 on failure or if the option is unknown
528 **/
529 int
raptor_turtle_writer_set_option(raptor_turtle_writer * turtle_writer,raptor_option option,int value)530 raptor_turtle_writer_set_option(raptor_turtle_writer *turtle_writer,
531 raptor_option option, int value)
532 {
533 if(value < 0 ||
534 !raptor_option_is_valid_for_area(option, RAPTOR_OPTION_AREA_TURTLE_WRITER))
535 return 1;
536
537 switch(option) {
538 case RAPTOR_OPTION_WRITER_AUTO_INDENT:
539 if(value)
540 turtle_writer->flags |= TURTLE_WRITER_AUTO_INDENT;
541 else
542 turtle_writer->flags &= ~TURTLE_WRITER_AUTO_INDENT;
543 break;
544
545 case RAPTOR_OPTION_WRITER_INDENT_WIDTH:
546 turtle_writer->indent = value;
547 break;
548
549 case RAPTOR_OPTION_WRITER_AUTO_EMPTY:
550 case RAPTOR_OPTION_WRITER_XML_VERSION:
551 case RAPTOR_OPTION_WRITER_XML_DECLARATION:
552 break;
553
554 /* parser options */
555 case RAPTOR_OPTION_SCANNING:
556 case RAPTOR_OPTION_ALLOW_NON_NS_ATTRIBUTES:
557 case RAPTOR_OPTION_ALLOW_OTHER_PARSETYPES:
558 case RAPTOR_OPTION_ALLOW_BAGID:
559 case RAPTOR_OPTION_ALLOW_RDF_TYPE_RDF_LIST:
560 case RAPTOR_OPTION_NORMALIZE_LANGUAGE:
561 case RAPTOR_OPTION_NON_NFC_FATAL:
562 case RAPTOR_OPTION_WARN_OTHER_PARSETYPES:
563 case RAPTOR_OPTION_CHECK_RDF_ID:
564 case RAPTOR_OPTION_HTML_TAG_SOUP:
565 case RAPTOR_OPTION_MICROFORMATS:
566 case RAPTOR_OPTION_HTML_LINK:
567 case RAPTOR_OPTION_WWW_TIMEOUT:
568 case RAPTOR_OPTION_STRICT:
569
570 /* Shared */
571 case RAPTOR_OPTION_NO_NET:
572 case RAPTOR_OPTION_NO_FILE:
573 case RAPTOR_OPTION_LOAD_EXTERNAL_ENTITIES:
574
575 /* XML writer options */
576 case RAPTOR_OPTION_RELATIVE_URIS:
577
578 /* DOT serializer options */
579 case RAPTOR_OPTION_RESOURCE_BORDER:
580 case RAPTOR_OPTION_LITERAL_BORDER:
581 case RAPTOR_OPTION_BNODE_BORDER:
582 case RAPTOR_OPTION_RESOURCE_FILL:
583 case RAPTOR_OPTION_LITERAL_FILL:
584 case RAPTOR_OPTION_BNODE_FILL:
585
586 /* JSON serializer options */
587 case RAPTOR_OPTION_JSON_CALLBACK:
588 case RAPTOR_OPTION_JSON_EXTRA_DATA:
589 case RAPTOR_OPTION_RSS_TRIPLES:
590 case RAPTOR_OPTION_ATOM_ENTRY_URI:
591 case RAPTOR_OPTION_PREFIX_ELEMENTS:
592
593 /* Turtle serializer option */
594 case RAPTOR_OPTION_WRITE_BASE_URI:
595
596 /* WWW option */
597 case RAPTOR_OPTION_WWW_HTTP_CACHE_CONTROL:
598 case RAPTOR_OPTION_WWW_HTTP_USER_AGENT:
599 case RAPTOR_OPTION_WWW_CERT_FILENAME:
600 case RAPTOR_OPTION_WWW_CERT_TYPE:
601 case RAPTOR_OPTION_WWW_CERT_PASSPHRASE:
602 case RAPTOR_OPTION_WWW_SSL_VERIFY_PEER:
603 case RAPTOR_OPTION_WWW_SSL_VERIFY_HOST:
604
605 default:
606 return -1;
607 }
608
609 return 0;
610 }
611
612
613 /**
614 * raptor_turtle_writer_set_option_string:
615 * @turtle_writer: #raptor_turtle_writer turtle_writer object
616 * @option: option to set from enumerated #raptor_option values
617 * @value: option value
618 *
619 * Set turtle_writer options with string values.
620 *
621 * The allowed options are available via
622 * raptor_world_get_option_description().
623 * If the option type is integer, the value is interpreted as an
624 * integer.
625 *
626 * Return value: non 0 on failure or if the option is unknown
627 **/
628 int
raptor_turtle_writer_set_option_string(raptor_turtle_writer * turtle_writer,raptor_option option,const unsigned char * value)629 raptor_turtle_writer_set_option_string(raptor_turtle_writer *turtle_writer,
630 raptor_option option,
631 const unsigned char *value)
632 {
633 if(!value ||
634 !raptor_option_is_valid_for_area(option, RAPTOR_OPTION_AREA_TURTLE_WRITER))
635 return 1;
636
637 if(raptor_option_value_is_numeric(option))
638 return raptor_turtle_writer_set_option(turtle_writer, option,
639 atoi((const char*)value));
640
641 return 1;
642 }
643
644
645 /**
646 * raptor_turtle_writer_get_option:
647 * @turtle_writer: #raptor_turtle_writer serializer object
648 * @option: option to get value
649 *
650 * Get various turtle_writer options.
651 *
652 * The allowed options are available via raptor_options_enumerate().
653 *
654 * Note: no option value is negative
655 *
656 * Return value: option value or < 0 for an illegal option
657 **/
658 int
raptor_turtle_writer_get_option(raptor_turtle_writer * turtle_writer,raptor_option option)659 raptor_turtle_writer_get_option(raptor_turtle_writer *turtle_writer,
660 raptor_option option)
661 {
662 int result = -1;
663
664 switch(option) {
665 case RAPTOR_OPTION_WRITER_AUTO_INDENT:
666 result = TURTLE_WRITER_AUTO_INDENT(turtle_writer);
667 break;
668
669 case RAPTOR_OPTION_WRITER_INDENT_WIDTH:
670 result = turtle_writer->indent;
671 break;
672
673 /* writer options */
674 case RAPTOR_OPTION_WRITER_AUTO_EMPTY:
675 case RAPTOR_OPTION_WRITER_XML_VERSION:
676 case RAPTOR_OPTION_WRITER_XML_DECLARATION:
677
678 /* parser options */
679 case RAPTOR_OPTION_SCANNING:
680 case RAPTOR_OPTION_ALLOW_NON_NS_ATTRIBUTES:
681 case RAPTOR_OPTION_ALLOW_OTHER_PARSETYPES:
682 case RAPTOR_OPTION_ALLOW_BAGID:
683 case RAPTOR_OPTION_ALLOW_RDF_TYPE_RDF_LIST:
684 case RAPTOR_OPTION_NORMALIZE_LANGUAGE:
685 case RAPTOR_OPTION_NON_NFC_FATAL:
686 case RAPTOR_OPTION_WARN_OTHER_PARSETYPES:
687 case RAPTOR_OPTION_CHECK_RDF_ID:
688 case RAPTOR_OPTION_HTML_TAG_SOUP:
689 case RAPTOR_OPTION_MICROFORMATS:
690 case RAPTOR_OPTION_HTML_LINK:
691 case RAPTOR_OPTION_WWW_TIMEOUT:
692 case RAPTOR_OPTION_STRICT:
693
694 /* Shared */
695 case RAPTOR_OPTION_NO_NET:
696 case RAPTOR_OPTION_NO_FILE:
697 case RAPTOR_OPTION_LOAD_EXTERNAL_ENTITIES:
698
699 /* XML writer options */
700 case RAPTOR_OPTION_RELATIVE_URIS:
701
702 /* DOT serializer options */
703 case RAPTOR_OPTION_RESOURCE_BORDER:
704 case RAPTOR_OPTION_LITERAL_BORDER:
705 case RAPTOR_OPTION_BNODE_BORDER:
706 case RAPTOR_OPTION_RESOURCE_FILL:
707 case RAPTOR_OPTION_LITERAL_FILL:
708 case RAPTOR_OPTION_BNODE_FILL:
709
710 /* JSON serializer options */
711 case RAPTOR_OPTION_JSON_CALLBACK:
712 case RAPTOR_OPTION_JSON_EXTRA_DATA:
713 case RAPTOR_OPTION_RSS_TRIPLES:
714 case RAPTOR_OPTION_ATOM_ENTRY_URI:
715 case RAPTOR_OPTION_PREFIX_ELEMENTS:
716
717 /* Turtle serializer option */
718 case RAPTOR_OPTION_WRITE_BASE_URI:
719
720 /* WWW option */
721 case RAPTOR_OPTION_WWW_HTTP_CACHE_CONTROL:
722 case RAPTOR_OPTION_WWW_HTTP_USER_AGENT:
723 case RAPTOR_OPTION_WWW_CERT_FILENAME:
724 case RAPTOR_OPTION_WWW_CERT_TYPE:
725 case RAPTOR_OPTION_WWW_CERT_PASSPHRASE:
726 case RAPTOR_OPTION_WWW_SSL_VERIFY_PEER:
727 case RAPTOR_OPTION_WWW_SSL_VERIFY_HOST:
728
729 default:
730 break;
731 }
732
733 return result;
734 }
735
736
737 /**
738 * raptor_turtle_writer_get_option_string:
739 * @turtle_writer: #raptor_turtle_writer serializer object
740 * @option: option to get value
741 *
742 * Get turtle_writer options with string values.
743 *
744 * The allowed options are available via raptor_options_enumerate().
745 *
746 * Return value: option value or NULL for an illegal option or no value
747 **/
748 const unsigned char *
raptor_turtle_writer_get_option_string(raptor_turtle_writer * turtle_writer,raptor_option option)749 raptor_turtle_writer_get_option_string(raptor_turtle_writer *turtle_writer,
750 raptor_option option)
751 {
752 return NULL;
753 }
754
755
756 /**
757 * raptor_turtle_writer_bnodeid:
758 * @turtle_writer: Turtle writer object
759 * @bnodeid: blank node ID to write
760 * @len: length of @bnodeid
761 *
762 * Write a blank node ID with leading _: to the Turtle writer.
763 *
764 **/
765 void
raptor_turtle_writer_bnodeid(raptor_turtle_writer * turtle_writer,const unsigned char * bnodeid,size_t len)766 raptor_turtle_writer_bnodeid(raptor_turtle_writer* turtle_writer,
767 const unsigned char *bnodeid, size_t len)
768 {
769 raptor_bnodeid_ntriples_write(bnodeid, len,
770 turtle_writer->iostr);
771 }
772
773
774 /**
775 * raptor_turtle_writer_uri:
776 * @turtle_writer: Turtle writer object
777 * @uri: uri
778 *
779 * Write a #raptor_uri to a turtle writer in qname or URI form
780 *
781 * Return value: non-0 on failure
782 */
783 int
raptor_turtle_writer_uri(raptor_turtle_writer * turtle_writer,raptor_uri * uri)784 raptor_turtle_writer_uri(raptor_turtle_writer* turtle_writer,
785 raptor_uri* uri)
786 {
787 raptor_qname* qname;
788 int rc = 0;
789
790 if(!uri)
791 return 1;
792
793 qname = raptor_new_qname_from_namespace_uri(turtle_writer->nstack, uri, 10);
794
795 /* XML Names allow leading '_' and '.' anywhere but Turtle does not */
796 if(qname && !raptor_turtle_is_legal_turtle_qname(qname)) {
797 raptor_free_qname(qname);
798 qname = NULL;
799 }
800
801 if(qname) {
802 raptor_turtle_writer_qname(turtle_writer, qname);
803 raptor_free_qname(qname);
804 } else {
805 rc = raptor_turtle_writer_reference(turtle_writer, uri);
806 }
807
808 return rc;
809 }
810
811
812 /**
813 * raptor_turtle_writer_term:
814 * @turtle_writer: Turtle writer object
815 * @term: term
816 *
817 * Write a #raptor_term to a turtle write
818 *
819 * Return value: non-0 on failure
820 */
821 int
raptor_turtle_writer_term(raptor_turtle_writer * turtle_writer,raptor_term * term)822 raptor_turtle_writer_term(raptor_turtle_writer* turtle_writer,
823 raptor_term* term)
824 {
825 int rc = 0;
826
827 if(!term)
828 return 1;
829
830 if(term->type == RAPTOR_TERM_TYPE_URI) {
831 rc = raptor_turtle_writer_uri(turtle_writer, term->value.uri);
832 } else if(term->type == RAPTOR_TERM_TYPE_LITERAL) {
833 rc = raptor_turtle_writer_literal(turtle_writer,
834 turtle_writer->nstack,
835 term->value.literal.string,
836 term->value.literal.language,
837 term->value.literal.datatype);
838 } else if(term->type == RAPTOR_TERM_TYPE_BLANK) {
839 rc = raptor_bnodeid_ntriples_write(term->value.blank.string,
840 term->value.blank.string_len,
841 turtle_writer->iostr);
842 } else {
843 rc = 2;
844 }
845
846 return rc;
847 }
848
849
850
851
852 #endif
853
854
855
856 #ifdef STANDALONE
857
858 /* one more prototype */
859 int main(int argc, char *argv[]);
860
861
862 const unsigned char *base_uri_string = (const unsigned char*)"http://example.org/base#";
863
864 const unsigned char* longstr = (const unsigned char*)"it's quoted\nand has newlines, \"s <> and\n\ttabbing";
865
866 #define OUT_BYTES_COUNT 149
867
868 int
main(int argc,char * argv[])869 main(int argc, char *argv[])
870 {
871 raptor_world *world;
872 const char *program = raptor_basename(argv[0]);
873 raptor_iostream *iostr;
874 raptor_namespace_stack *nstack;
875 raptor_namespace* ex_ns;
876 raptor_turtle_writer* turtle_writer;
877 raptor_uri* base_uri;
878 raptor_qname* el_name;
879 unsigned long count;
880
881 /* for raptor_new_iostream_to_string */
882 void *string = NULL;
883 size_t string_len = 0;
884
885 world = raptor_new_world();
886 if(!world || raptor_world_open(world))
887 exit(1);
888
889 iostr = raptor_new_iostream_to_string(world, &string, &string_len, NULL);
890 if(!iostr) {
891 fprintf(stderr, "%s: Failed to create iostream to string\n", program);
892 exit(1);
893 }
894
895 nstack = raptor_new_namespaces(world, 1);
896
897 base_uri = raptor_new_uri(world, base_uri_string);
898
899 turtle_writer = raptor_new_turtle_writer(world, base_uri, 1, nstack, iostr);
900 if(!turtle_writer) {
901 fprintf(stderr, "%s: Failed to create turtle_writer to iostream\n", program);
902 exit(1);
903 }
904
905 raptor_turtle_writer_set_option(turtle_writer,
906 RAPTOR_OPTION_WRITER_AUTO_INDENT, 1);
907
908 ex_ns = raptor_new_namespace(nstack,
909 (const unsigned char*)"ex",
910 (const unsigned char*)"http://example.org/ns#",
911 0);
912
913
914 raptor_turtle_writer_namespace_prefix(turtle_writer, ex_ns);
915
916 raptor_turtle_writer_reference(turtle_writer, base_uri);
917
918 raptor_turtle_writer_increase_indent(turtle_writer);
919 raptor_turtle_writer_newline(turtle_writer);
920
921 raptor_turtle_writer_raw(turtle_writer, (const unsigned char*)"ex:foo ");
922
923 raptor_turtle_writer_quoted_counted_string(turtle_writer, longstr,
924 strlen((const char*)longstr));
925 raptor_turtle_writer_raw_counted(turtle_writer,
926 (const unsigned char*)" ;", 2);
927 raptor_turtle_writer_newline(turtle_writer);
928
929 el_name = raptor_new_qname_from_namespace_local_name(world,
930 ex_ns,
931 (const unsigned char*)"bar",
932 NULL);
933
934 raptor_turtle_writer_qname(turtle_writer, el_name);
935 raptor_free_qname(el_name);
936
937 raptor_turtle_writer_raw_counted(turtle_writer, (const unsigned char*)" ", 1);
938
939 raptor_turtle_writer_literal(turtle_writer, nstack,
940 (const unsigned char*)"10.0", NULL,
941 world->xsd_decimal_uri);
942
943 raptor_turtle_writer_newline(turtle_writer);
944
945 raptor_turtle_writer_decrease_indent(turtle_writer);
946
947 raptor_turtle_writer_raw_counted(turtle_writer, (const unsigned char*)".", 1);
948 raptor_turtle_writer_newline(turtle_writer);
949
950
951 raptor_free_turtle_writer(turtle_writer);
952
953 raptor_free_namespace(ex_ns);
954
955 raptor_free_namespaces(nstack);
956
957 raptor_free_uri(base_uri);
958
959
960 count = raptor_iostream_tell(iostr);
961
962 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
963 fprintf(stderr, "%s: Freeing iostream\n", program);
964 #endif
965 raptor_free_iostream(iostr);
966
967 if(count != OUT_BYTES_COUNT) {
968 fprintf(stderr, "%s: I/O stream wrote %d bytes, expected %d\n", program,
969 (int)count, (int)OUT_BYTES_COUNT);
970 fputs("[[", stderr);
971 (void)fwrite(string, 1, string_len, stderr);
972 fputs("]]\n", stderr);
973 return 1;
974 }
975
976 if(!string) {
977 fprintf(stderr, "%s: I/O stream failed to create a string\n", program);
978 return 1;
979 }
980 string_len = strlen((const char*)string);
981 if(string_len != count) {
982 fprintf(stderr, "%s: I/O stream created a string length %d, expected %d\n", program, (int)string_len, (int)count);
983 return 1;
984 }
985
986 #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1
987 fprintf(stderr, "%s: Made Turtle string of %d bytes\n", program, (int)string_len);
988 fputs("[[", stderr);
989 (void)fwrite(string, 1, string_len, stderr);
990 fputs("]]\n", stderr);
991 #endif
992
993 raptor_free_memory(string);
994
995 raptor_free_world(world);
996
997 /* keep gcc -Wall happy */
998 return(0);
999 }
1000
1001 #endif
1002