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