1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * raptor_json_writer.c - Raptor JSON Writer
4  *
5  * Copyright (C) 2008, David Beckett http://www.dajobe.org/
6  *
7  * This package is Free Software and part of Redland http://librdf.org/
8  *
9  * It is licensed under the following three licenses as alternatives:
10  *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
11  *   2. GNU General Public License (GPL) V2 or any newer version
12  *   3. Apache License, V2.0 or any newer version
13  *
14  * You may not use this file except in compliance with at least one of
15  * the above three licenses.
16  *
17  * See LICENSE.html or LICENSE.txt at the top of this package for the
18  * complete terms and further detail along with the license texts for
19  * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
20  *
21  *
22  */
23 
24 
25 #ifdef HAVE_CONFIG_H
26 #include <raptor_config.h>
27 #endif
28 
29 #ifdef WIN32
30 #include <win32_raptor_config.h>
31 #endif
32 
33 
34 #include <stdio.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdarg.h>
38 #ifdef HAVE_ERRNO_H
39 #include <errno.h>
40 #endif
41 #ifdef HAVE_STDLIB_H
42 #include <stdlib.h>
43 #endif
44 #ifdef HAVE_LIMITS_H
45 #include <limits.h>
46 #endif
47 
48 
49 /* Raptor includes */
50 #include "raptor.h"
51 #include "raptor_internal.h"
52 
53 #ifndef STANDALONE
54 
55 #ifndef RAPTOR_JSON_WRITER_DATATYPES
56 #define RAPTOR_JSON_WRITER_DATATYPES 0
57 #endif
58 
59 struct raptor_json_writer_s {
60   raptor_world* world;
61 
62   raptor_uri* base_uri;
63 
64   raptor_simple_message_handler error_handler;
65   void *error_data;
66 
67   /* outputting to this iostream */
68   raptor_iostream *iostr;
69 
70 #if RAPTOR_JSON_WRITER_DATATYPES == 1
71   raptor_uri* xsd_boolean_uri;
72   raptor_uri* xsd_decimal_uri;
73   raptor_uri* xsd_double_uri;
74   raptor_uri* xsd_integer_uri;
75 #endif
76 
77   /* current indent */
78   int indent;
79 
80   /* indent step */
81   int indent_step;
82 };
83 
84 
85 
86 /**
87  * raptor_new_json_writer:
88  * @world: raptor_world object
89  * @base_uri: Base URI for the writer
90  * @iostr: I/O stream to write to
91  * @error_handler: error handler function
92  * @error_data: error handler data
93  *
94  * INTERNAL - Constructor - Create a new JSON writer writing to a raptor_iostream
95  *
96  * Return value: a new #raptor_json_writer object or NULL on failure
97  **/
98 raptor_json_writer*
raptor_new_json_writer(raptor_world * world,raptor_uri * base_uri,raptor_iostream * iostr,raptor_simple_message_handler error_handler,void * error_data)99 raptor_new_json_writer(raptor_world* world,
100                        raptor_uri* base_uri,
101                        raptor_iostream* iostr,
102                        raptor_simple_message_handler error_handler,
103                        void *error_data)
104 {
105   raptor_json_writer* json_writer;
106 
107   json_writer=(raptor_json_writer*)RAPTOR_CALLOC(raptor_json_writer, 1, sizeof(raptor_json_writer)+1);
108 
109   if(!json_writer)
110     return NULL;
111 
112   json_writer->world=world;
113   json_writer->error_handler=error_handler;
114   json_writer->error_data=error_data;
115   json_writer->iostr=iostr;
116   json_writer->base_uri=base_uri;
117 
118 #if RAPTOR_JSON_WRITER_DATATYPES == 1
119   json_writer->xsd_boolean_uri=raptor_new_uri_v2(world, (const unsigned char*)"http://www.w3.org/2001/XMLSchema#boolean");
120   json_writer->xsd_decimal_uri=raptor_new_uri_v2(world, (const unsigned char*)"http://www.w3.org/2001/XMLSchema#decimal");
121   json_writer->xsd_double_uri=raptor_new_uri_v2(world, (const unsigned char*)"http://www.w3.org/2001/XMLSchema#double");
122   json_writer->xsd_integer_uri=raptor_new_uri_v2(world, (const unsigned char*)"http://www.w3.org/2001/XMLSchema#integer");
123 #endif
124 
125   json_writer->indent_step=2;
126 
127   return json_writer;
128 }
129 
130 
131 /**
132  * raptor_free_json_writer:
133  * @json_writer: JSON writer object
134  *
135  * INTERNAL - Destructor - Free JSON Writer
136  *
137  **/
138 void
raptor_free_json_writer(raptor_json_writer * json_writer)139 raptor_free_json_writer(raptor_json_writer* json_writer)
140 {
141   RAPTOR_ASSERT_OBJECT_POINTER_RETURN(json_writer, raptor_json_writer);
142 
143 #if RAPTOR_JSON_WRITER_DATATYPES == 1
144   if(json_writer->xsd_boolean_uri)
145     raptor_free_uri_v2(json_writer->world, json_writer->xsd_boolean_uri);
146   if(json_writer->xsd_decimal_uri)
147     raptor_free_uri_v2(json_writer->world, json_writer->xsd_decimal_uri);
148   if(json_writer->xsd_double_uri)
149     raptor_free_uri_v2(json_writer->world, json_writer->xsd_double_uri);
150   if(json_writer->xsd_integer_uri)
151     raptor_free_uri_v2(json_writer->world, json_writer->xsd_integer_uri);
152 #endif
153 
154   RAPTOR_FREE(raptor_json_writer, json_writer);
155 }
156 
157 
158 static int
raptor_json_writer_quoted(raptor_json_writer * json_writer,const char * value,size_t value_len)159 raptor_json_writer_quoted(raptor_json_writer* json_writer,
160                           const char *value, size_t value_len)
161 {
162   if(!value) {
163     raptor_iostream_write_counted_string(json_writer->iostr, "\"\"", 2);
164     return 0;
165   }
166   if(!value_len)
167     value_len=strlen((const char*)value);
168 
169   raptor_iostream_write_byte(json_writer->iostr, '\"');
170   raptor_iostream_write_string_python(json_writer->iostr,
171                                       (const unsigned char*)value, value_len,
172                                       '"', 3);
173   raptor_iostream_write_byte(json_writer->iostr, '\"');
174 
175   return 0;
176 }
177 
178 
179 static int
raptor_json_writer_spaces(raptor_json_writer * json_writer,int depth)180 raptor_json_writer_spaces(raptor_json_writer* json_writer, int depth)
181 {
182   int i;
183   for(i=0; i<depth; i++)
184     raptor_iostream_write_byte(json_writer->iostr, ' ');
185   return 0;
186 }
187 
188 
189 int
raptor_json_writer_newline(raptor_json_writer * json_writer)190 raptor_json_writer_newline(raptor_json_writer* json_writer)
191 {
192   raptor_iostream_write_byte(json_writer->iostr, '\n');
193   if(json_writer->indent)
194     raptor_json_writer_spaces(json_writer, json_writer->indent);
195   return 0;
196 }
197 
198 
199 int
raptor_json_writer_key_value(raptor_json_writer * json_writer,const char * key,size_t key_len,const char * value,size_t value_len)200 raptor_json_writer_key_value(raptor_json_writer* json_writer,
201                              const char* key, size_t key_len,
202                              const char* value, size_t value_len)
203 {
204   if(!key_len && key)
205     key_len=strlen(key);
206   if(!value_len && value)
207     value_len=strlen(value);
208 
209   raptor_json_writer_quoted(json_writer, key, key_len);
210   raptor_iostream_write_counted_string(json_writer->iostr, " : ", 3);
211   raptor_json_writer_quoted(json_writer, value, value_len);
212 
213   return 0;
214 }
215 
216 
217 int
raptor_json_writer_key_uri_value(raptor_json_writer * json_writer,const char * key,size_t key_len,raptor_uri * uri)218 raptor_json_writer_key_uri_value(raptor_json_writer* json_writer,
219                                  const char* key, size_t key_len,
220                                  raptor_uri* uri)
221 {
222   const char* value;
223   size_t value_len;
224   int rc=0;
225 
226   value=(const char*)raptor_uri_to_relative_counted_uri_string_v2(json_writer->world, json_writer->base_uri, uri, &value_len);
227   if(!value)
228     return 1;
229 
230   if(key)
231     rc=raptor_json_writer_key_value(json_writer, key, key_len,
232                                     value, value_len);
233   else
234     rc=raptor_json_writer_quoted(json_writer, value, value_len);
235 
236   RAPTOR_FREE(cstring, value);
237 
238   return 0;
239 }
240 
241 
242 int
raptor_json_writer_start_block(raptor_json_writer * json_writer,char c)243 raptor_json_writer_start_block(raptor_json_writer* json_writer, char c)
244 {
245   json_writer->indent += json_writer->indent_step;
246   raptor_iostream_write_byte(json_writer->iostr, c);
247   return 0;
248 }
249 
250 
251 int
raptor_json_writer_end_block(raptor_json_writer * json_writer,char c)252 raptor_json_writer_end_block(raptor_json_writer* json_writer, char c)
253 {
254   raptor_iostream_write_byte(json_writer->iostr, c);
255   json_writer->indent -= json_writer->indent_step;
256   return 0;
257 }
258 
259 
260 int
raptor_json_writer_literal_object(raptor_json_writer * json_writer,unsigned char * s,unsigned char * lang,raptor_uri * datatype,const char * key,const char * type_key)261 raptor_json_writer_literal_object(raptor_json_writer* json_writer,
262                                   unsigned char* s, unsigned char* lang,
263                                   raptor_uri* datatype,
264                                   const char* key, const char* type_key)
265 {
266 
267   if(key) {
268     raptor_json_writer_start_block(json_writer, '{');
269     raptor_json_writer_newline(json_writer);
270 
271     raptor_json_writer_quoted(json_writer, key, 0);
272 
273     raptor_iostream_write_counted_string(json_writer->iostr, " : ", 3);
274   }
275 
276   raptor_json_writer_quoted(json_writer, (const char*)s, 0);
277 
278   if(datatype || lang) {
279     raptor_iostream_write_byte(json_writer->iostr, ',');
280     raptor_json_writer_newline(json_writer);
281 
282     if(datatype)
283       raptor_json_writer_key_uri_value(json_writer, "datatype", 8, datatype);
284 
285     if(lang) {
286       if(datatype) {
287         raptor_iostream_write_byte(json_writer->iostr, ',');
288         raptor_json_writer_newline(json_writer);
289       }
290 
291       raptor_json_writer_key_value(json_writer, "lang", 4,
292                                    (const char*)lang, 0);
293     }
294   }
295 
296   if(type_key) {
297     raptor_iostream_write_byte(json_writer->iostr, ',');
298     raptor_json_writer_newline(json_writer);
299 
300     raptor_json_writer_key_value(json_writer, type_key, 0, "literal", 0);
301   }
302 
303   raptor_json_writer_newline(json_writer);
304 
305   if(key) {
306     raptor_json_writer_end_block(json_writer, '}');
307     raptor_json_writer_newline(json_writer);
308   }
309 
310   return 0;
311 }
312 
313 
314 /* not used here */
315 
316 #if RAPTOR_JSON_WRITER_DATATYPES == 1
317 int raptor_json_writer_literal_datatype(raptor_json_writer* json_writer, raptor_namespace_stack *nstack, unsigned char* s, unsigned char* lang, raptor_uri* datatype);
318 
319 
320 int
raptor_json_writer_literal_datatype(raptor_json_writer * json_writer,raptor_namespace_stack * nstack,unsigned char * s,unsigned char * lang,raptor_uri * datatype)321 raptor_json_writer_literal_datatype(raptor_json_writer* json_writer,
322                                     raptor_namespace_stack *nstack,
323                                     unsigned char* s, unsigned char* lang,
324                                     raptor_uri* datatype)
325 {
326   /* DBL_MAX = 309 decimal digits */
327   #define INT_MAX_LEN 309
328 
329   /* DBL_EPSILON = 52 digits */
330   #define FRAC_MAX_LEN 52
331 
332   const size_t buflen = INT_MAX_LEN + FRAC_MAX_LEN + 3; /* sign, decimal, \0 */
333   char buf[buflen];
334 
335   size_t len = 0;
336   char* endptr = (char *)s;
337   int written = 0;
338 
339   /* typed literal special cases */
340   if(datatype) {
341     /* integer */
342     if(raptor_uri_equals_v2(json_writer->world, datatype, json_writer->xsd_integer_uri)) {
343       long inum = strtol((const char*)s, NULL, 10);
344       if(inum != LONG_MIN && inum != LONG_MAX) {
345         raptor_iostream_write_decimal(json_writer->iostr, inum);
346         written = 1;
347       }
348 
349     /* double */
350     } else if(raptor_uri_equals_v2(json_writer->world, datatype, json_writer->xsd_double_uri)) {
351       double dnum = strtod((const char*)s, &endptr);
352       if(endptr != (char*)s) {
353         const char* decimal = strchr((const char*)s, '.');
354         const size_t max_digits = (decimal ? (endptr - decimal - 2) : 1);
355         char* num_str;
356 
357         num_str=raptor_format_float(buf, &len, buflen, dnum, 1, max_digits, 0);
358         raptor_iostream_write_counted_string(json_writer->iostr, num_str, len);
359         written = 1;
360       }
361 
362     /* decimal */
363     } else if(raptor_uri_equals_v2(json_writer->world, datatype, json_writer->xsd_decimal_uri)) {
364       double dnum = strtod((const char*)s, &endptr);
365       if(endptr != (char*)s) {
366         snprintf(buf, 20, "%.1lf", dnum);
367         raptor_iostream_write_string(json_writer->iostr, buf);
368         written = 1;
369       }
370 
371     /* boolean */
372     } else if(raptor_uri_equals_v2(json_writer->world, datatype, json_writer->xsd_boolean_uri)) {
373       if(!strcmp((const char*)s, "0") || !strcmp((const char*)s, "false")) {
374         raptor_iostream_write_string(json_writer->iostr, "false");
375         written = 1;
376       } else if(!strcmp((const char*)s, "1") || !strcmp((const char*)s, "true")) {
377         raptor_iostream_write_string(json_writer->iostr, "true");
378         written = 1;
379       } else {
380         json_writer->error_handler(json_writer->error_data, "Illegal value for xsd:boolean literal.");
381         return 1;
382       }
383     }
384   }
385 
386   if(written)
387     return 0;
388 
389   return raptor_json_writer_literal_object(json_writer,
390                                            s, lang, datatype, "value", NULL);
391 }
392 #endif
393 
394 
395 int
raptor_json_writer_blank_object(raptor_json_writer * json_writer,const char * blank)396 raptor_json_writer_blank_object(raptor_json_writer* json_writer,
397                                 const char* blank)
398 {
399   raptor_json_writer_start_block(json_writer, '{');
400   raptor_json_writer_newline(json_writer);
401 
402   raptor_iostream_write_counted_string(json_writer->iostr,
403                                        "\"value\" : \"_:", 13);
404   raptor_iostream_write_string(json_writer->iostr, blank);
405   raptor_iostream_write_counted_string(json_writer->iostr, "\",", 2);
406   raptor_json_writer_newline(json_writer);
407 
408   raptor_iostream_write_counted_string(json_writer->iostr,
409                                        "\"type\" : \"bnode\"", 16);
410   raptor_json_writer_newline(json_writer);
411 
412   raptor_json_writer_end_block(json_writer, '}');
413   return 0;
414 }
415 
416 
417 int
raptor_json_writer_uri_object(raptor_json_writer * json_writer,raptor_uri * uri)418 raptor_json_writer_uri_object(raptor_json_writer* json_writer,
419                               raptor_uri* uri)
420 {
421   raptor_json_writer_start_block(json_writer, '{');
422   raptor_json_writer_newline(json_writer);
423 
424   raptor_json_writer_key_uri_value(json_writer, "value", 5, uri);
425   raptor_iostream_write_byte(json_writer->iostr, ',');
426   raptor_json_writer_newline(json_writer);
427 
428   raptor_iostream_write_counted_string(json_writer->iostr,
429                                        "\"type\" : \"uri\"", 14);
430   raptor_json_writer_newline(json_writer);
431 
432   raptor_json_writer_end_block(json_writer, '}');
433 
434   return 0;
435 }
436 
437 #endif
438