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