mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-28 14:18:41 +02:00
441 lines
12 KiB
C
441 lines
12 KiB
C
/* -*- Mode: c; c-basic-offset: 2 -*-
|
|
*
|
|
* raptor_json_writer.c - Raptor JSON Writer
|
|
*
|
|
* Copyright (C) 2008, David Beckett http://purl.org/net/dajobe/
|
|
*
|
|
* This package is Free Software and part of Redland http://librdf.org/
|
|
*
|
|
* It is licensed under the following three licenses as alternatives:
|
|
* 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
|
|
* 2. GNU General Public License (GPL) V2 or any newer version
|
|
* 3. Apache License, V2.0 or any newer version
|
|
*
|
|
* You may not use this file except in compliance with at least one of
|
|
* the above three licenses.
|
|
*
|
|
* See LICENSE.html or LICENSE.txt at the top of this package for the
|
|
* complete terms and further detail along with the license texts for
|
|
* the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <raptor_config.h>
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#include <win32_raptor_config.h>
|
|
#endif
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdarg.h>
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#ifdef HAVE_LIMITS_H
|
|
#include <limits.h>
|
|
#endif
|
|
|
|
|
|
/* Raptor includes */
|
|
#include "raptor.h"
|
|
#include "raptor_internal.h"
|
|
|
|
#ifndef STANDALONE
|
|
|
|
#ifndef RAPTOR_JSON_WRITER_DATATYPES
|
|
#define RAPTOR_JSON_WRITER_DATATYPES 0
|
|
#endif
|
|
|
|
struct raptor_json_writer_s {
|
|
raptor_uri* base_uri;
|
|
|
|
const raptor_uri_handler *uri_handler;
|
|
void *uri_context;
|
|
|
|
raptor_simple_message_handler error_handler;
|
|
void *error_data;
|
|
|
|
/* outputting to this iostream */
|
|
raptor_iostream *iostr;
|
|
|
|
#if RAPTOR_JSON_WRITER_DATATYPES == 1
|
|
raptor_uri* xsd_boolean_uri;
|
|
raptor_uri* xsd_decimal_uri;
|
|
raptor_uri* xsd_double_uri;
|
|
raptor_uri* xsd_integer_uri;
|
|
#endif
|
|
|
|
/* current indent */
|
|
int indent;
|
|
|
|
/* indent step */
|
|
int indent_step;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* raptor_new_json_writer:
|
|
* @base_uri: Base URI for the writer
|
|
* @uri_handler: URI handler function
|
|
* @uri_context: URI handler context data
|
|
* @iostr: I/O stream to write to
|
|
* @error_handler: error handler function
|
|
* @error_data: error handler data
|
|
*
|
|
* Constructor - Create a new JSON writer writing to a raptor_iostream
|
|
*
|
|
* Return value: a new #raptor_json_writer object or NULL on failure
|
|
**/
|
|
raptor_json_writer*
|
|
raptor_new_json_writer(raptor_uri* base_uri,
|
|
const raptor_uri_handler *uri_handler,
|
|
void *uri_context,
|
|
raptor_iostream* iostr,
|
|
raptor_simple_message_handler error_handler,
|
|
void *error_data)
|
|
{
|
|
raptor_json_writer* json_writer;
|
|
|
|
json_writer=(raptor_json_writer*)RAPTOR_CALLOC(raptor_json_writer, 1, sizeof(raptor_json_writer)+1);
|
|
|
|
if(!json_writer)
|
|
return NULL;
|
|
|
|
json_writer->uri_handler=uri_handler;
|
|
json_writer->uri_context=uri_context;
|
|
json_writer->error_handler=error_handler;
|
|
json_writer->error_data=error_data;
|
|
json_writer->iostr=iostr;
|
|
json_writer->base_uri=base_uri;
|
|
|
|
#if RAPTOR_JSON_WRITER_DATATYPES == 1
|
|
json_writer->xsd_boolean_uri=raptor_new_uri((const unsigned char*)"http://www.w3.org/2001/XMLSchema#boolean");
|
|
json_writer->xsd_decimal_uri=raptor_new_uri((const unsigned char*)"http://www.w3.org/2001/XMLSchema#decimal");
|
|
json_writer->xsd_double_uri=raptor_new_uri((const unsigned char*)"http://www.w3.org/2001/XMLSchema#double");
|
|
json_writer->xsd_integer_uri=raptor_new_uri((const unsigned char*)"http://www.w3.org/2001/XMLSchema#integer");
|
|
#endif
|
|
|
|
json_writer->indent_step=2;
|
|
|
|
return json_writer;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_free_json_writer:
|
|
* @json_writer: JSON writer object
|
|
*
|
|
* Destructor - Free JSON Writer
|
|
*
|
|
**/
|
|
void
|
|
raptor_free_json_writer(raptor_json_writer* json_writer)
|
|
{
|
|
|
|
#if RAPTOR_JSON_WRITER_DATATYPES == 1
|
|
if(json_writer->xsd_boolean_uri)
|
|
raptor_free_uri(json_writer->xsd_boolean_uri);
|
|
if(json_writer->xsd_decimal_uri)
|
|
raptor_free_uri(json_writer->xsd_decimal_uri);
|
|
if(json_writer->xsd_double_uri)
|
|
raptor_free_uri(json_writer->xsd_double_uri);
|
|
if(json_writer->xsd_integer_uri)
|
|
raptor_free_uri(json_writer->xsd_integer_uri);
|
|
#endif
|
|
|
|
RAPTOR_FREE(raptor_json_writer, json_writer);
|
|
}
|
|
|
|
|
|
static int
|
|
raptor_json_writer_quoted(raptor_json_writer* json_writer,
|
|
const char *value, size_t value_len)
|
|
{
|
|
if(!value) {
|
|
raptor_iostream_write_counted_string(json_writer->iostr, "\"\"", 2);
|
|
return 0;
|
|
}
|
|
if(!value_len)
|
|
value_len=strlen((const char*)value);
|
|
|
|
raptor_iostream_write_byte(json_writer->iostr, '\"');
|
|
raptor_iostream_write_string_python(json_writer->iostr,
|
|
(const unsigned char*)value, value_len,
|
|
'"', 3);
|
|
raptor_iostream_write_byte(json_writer->iostr, '\"');
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
raptor_json_writer_spaces(raptor_json_writer* json_writer, int depth)
|
|
{
|
|
int i;
|
|
for(i=0; i<depth; i++)
|
|
raptor_iostream_write_byte(json_writer->iostr, ' ');
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
raptor_json_writer_newline(raptor_json_writer* json_writer)
|
|
{
|
|
raptor_iostream_write_byte(json_writer->iostr, '\n');
|
|
if(json_writer->indent)
|
|
raptor_json_writer_spaces(json_writer, json_writer->indent);
|
|
return 0;
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
if(!key_len && key)
|
|
key_len=strlen(key);
|
|
if(!value_len && value)
|
|
value_len=strlen(value);
|
|
|
|
raptor_json_writer_quoted(json_writer, key, key_len);
|
|
raptor_iostream_write_counted_string(json_writer->iostr, " : ", 3);
|
|
raptor_json_writer_quoted(json_writer, value, value_len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
raptor_json_writer_key_uri_value(raptor_json_writer* json_writer,
|
|
const char* key, size_t key_len,
|
|
raptor_uri* uri)
|
|
{
|
|
const char* value;
|
|
size_t value_len;
|
|
int rc=0;
|
|
|
|
value=(const char*)raptor_uri_to_relative_counted_uri_string(json_writer->base_uri, uri, &value_len);
|
|
if(!value)
|
|
return 1;
|
|
|
|
if(key)
|
|
rc=raptor_json_writer_key_value(json_writer, key, key_len,
|
|
value, value_len);
|
|
else
|
|
rc=raptor_json_writer_quoted(json_writer, value, value_len);
|
|
|
|
RAPTOR_FREE(cstring, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
raptor_json_writer_start_block(raptor_json_writer* json_writer, char c)
|
|
{
|
|
json_writer->indent += json_writer->indent_step;
|
|
raptor_iostream_write_byte(json_writer->iostr, c);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
raptor_json_writer_end_block(raptor_json_writer* json_writer, char c)
|
|
{
|
|
raptor_iostream_write_byte(json_writer->iostr, c);
|
|
json_writer->indent -= json_writer->indent_step;
|
|
return 0;
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
|
|
if(key) {
|
|
raptor_json_writer_start_block(json_writer, '{');
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_json_writer_quoted(json_writer, key, 0);
|
|
|
|
raptor_iostream_write_counted_string(json_writer->iostr, " : ", 3);
|
|
}
|
|
|
|
raptor_json_writer_quoted(json_writer, (const char*)s, 0);
|
|
|
|
if(datatype || lang) {
|
|
raptor_iostream_write_byte(json_writer->iostr, ',');
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
if(datatype)
|
|
raptor_json_writer_key_uri_value(json_writer, "datatype", 8, datatype);
|
|
|
|
if(lang) {
|
|
if(datatype) {
|
|
raptor_iostream_write_byte(json_writer->iostr, ',');
|
|
raptor_json_writer_newline(json_writer);
|
|
}
|
|
|
|
raptor_json_writer_key_value(json_writer, "lang", 4,
|
|
(const char*)lang, 0);
|
|
}
|
|
}
|
|
|
|
if(type_key) {
|
|
raptor_iostream_write_byte(json_writer->iostr, ',');
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_json_writer_key_value(json_writer, type_key, 0, "literal", 0);
|
|
}
|
|
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
if(key) {
|
|
raptor_json_writer_end_block(json_writer, '}');
|
|
raptor_json_writer_newline(json_writer);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* not used here */
|
|
|
|
#if RAPTOR_JSON_WRITER_DATATYPES == 1
|
|
int raptor_json_writer_literal_datatype(raptor_json_writer* json_writer, raptor_namespace_stack *nstack, unsigned char* s, unsigned char* lang, raptor_uri* datatype);
|
|
|
|
|
|
int
|
|
raptor_json_writer_literal_datatype(raptor_json_writer* json_writer,
|
|
raptor_namespace_stack *nstack,
|
|
unsigned char* s, unsigned char* lang,
|
|
raptor_uri* datatype)
|
|
{
|
|
/* DBL_MAX = 309 decimal digits */
|
|
#define INT_MAX_LEN 309
|
|
|
|
/* DBL_EPSILON = 52 digits */
|
|
#define FRAC_MAX_LEN 52
|
|
|
|
const size_t buflen = INT_MAX_LEN + FRAC_MAX_LEN + 3; /* sign, decimal, \0 */
|
|
char buf[buflen];
|
|
|
|
size_t len = 0;
|
|
char* endptr = (char *)s;
|
|
int written = 0;
|
|
|
|
/* typed literal special cases */
|
|
if(datatype) {
|
|
/* integer */
|
|
if(raptor_uri_equals(datatype, json_writer->xsd_integer_uri)) {
|
|
long inum = strtol((const char*)s, NULL, 10);
|
|
if(inum != LONG_MIN && inum != LONG_MAX) {
|
|
raptor_iostream_write_decimal(json_writer->iostr, inum);
|
|
written = 1;
|
|
}
|
|
|
|
/* double */
|
|
} else if(raptor_uri_equals(datatype, json_writer->xsd_double_uri)) {
|
|
double dnum = strtod((const char*)s, &endptr);
|
|
if(endptr != (char*)s) {
|
|
const char* decimal = strchr((const char*)s, '.');
|
|
const size_t max_digits = (decimal ? (endptr - decimal - 2) : 1);
|
|
char* num_str;
|
|
|
|
num_str=raptor_format_float(buf, &len, buflen, dnum, 1, max_digits, 0);
|
|
raptor_iostream_write_counted_string(json_writer->iostr, num_str, len);
|
|
written = 1;
|
|
}
|
|
|
|
/* decimal */
|
|
} else if(raptor_uri_equals(datatype, json_writer->xsd_decimal_uri)) {
|
|
double dnum = strtod((const char*)s, &endptr);
|
|
if(endptr != (char*)s) {
|
|
snprintf(buf, 20, "%.1lf", dnum);
|
|
raptor_iostream_write_string(json_writer->iostr, buf);
|
|
written = 1;
|
|
}
|
|
|
|
/* boolean */
|
|
} else if(raptor_uri_equals(datatype, json_writer->xsd_boolean_uri)) {
|
|
if(!strcmp((const char*)s, "0") || !strcmp((const char*)s, "false")) {
|
|
raptor_iostream_write_string(json_writer->iostr, "false");
|
|
written = 1;
|
|
} else if(!strcmp((const char*)s, "1") || !strcmp((const char*)s, "true")) {
|
|
raptor_iostream_write_string(json_writer->iostr, "true");
|
|
written = 1;
|
|
} else {
|
|
json_writer->error_handler(json_writer->error_data, "Illegal value for xsd:boolean literal.");
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(written)
|
|
return 0;
|
|
|
|
return raptor_json_writer_literal_object(json_writer,
|
|
s, lang, datatype, "value", NULL);
|
|
}
|
|
#endif
|
|
|
|
|
|
int
|
|
raptor_json_writer_blank_object(raptor_json_writer* json_writer,
|
|
const char* blank)
|
|
{
|
|
raptor_json_writer_start_block(json_writer, '{');
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_iostream_write_counted_string(json_writer->iostr,
|
|
"\"value\" : \"_:", 13);
|
|
raptor_iostream_write_string(json_writer->iostr, blank);
|
|
raptor_iostream_write_counted_string(json_writer->iostr, "\",", 2);
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_iostream_write_counted_string(json_writer->iostr,
|
|
"\"type\" : \"bnode\"", 16);
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_json_writer_end_block(json_writer, '}');
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
raptor_json_writer_uri_object(raptor_json_writer* json_writer,
|
|
raptor_uri* uri)
|
|
{
|
|
raptor_json_writer_start_block(json_writer, '{');
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_json_writer_key_uri_value(json_writer, "value", 5, uri);
|
|
raptor_iostream_write_byte(json_writer->iostr, ',');
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_iostream_write_counted_string(json_writer->iostr,
|
|
"\"type\" : \"uri\"", 14);
|
|
raptor_json_writer_newline(json_writer);
|
|
|
|
raptor_json_writer_end_block(json_writer, '}');
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|