/* -*- Mode: c; c-basic-offset: 2 -*- * * raptor_serialize.c - Raptor Serializer API * * Copyright (C) 2004-2010, David Beckett http://www.dajobe.org/ * Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/ * * 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 #endif #include #include #include #include #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_STDLIB_H #include #endif /* Raptor includes */ #include "raptor2.h" #include "raptor_internal.h" /* prototypes for helper functions */ static raptor_serializer_factory* raptor_get_serializer_factory(raptor_world* world, const char *name); /* helper methods */ static void raptor_free_serializer_factory(raptor_serializer_factory* factory) { RAPTOR_ASSERT_OBJECT_POINTER_RETURN(factory, raptor_serializer_factory); if(factory->finish_factory) factory->finish_factory(factory); RAPTOR_FREE(raptor_serializer_factory, factory); } /* class methods */ int raptor_serializers_init(raptor_world* world) { int rc = 0; world->serializers = raptor_new_sequence((raptor_data_free_handler)raptor_free_serializer_factory, NULL); if(!world->serializers) return 1; #ifdef RAPTOR_SERIALIZER_NTRIPLES rc += raptor_init_serializer_ntriples(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_TURTLE rc += raptor_init_serializer_turtle(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_MKR rc += raptor_init_serializer_mkr(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_RDFXML_ABBREV rc += raptor_init_serializer_rdfxmla(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_RDFXML rc += raptor_init_serializer_rdfxml(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_RSS_1_0 rc += raptor_init_serializer_rss10(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_ATOM rc += raptor_init_serializer_atom(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_DOT rc += raptor_init_serializer_dot(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_JSON rc += raptor_init_serializer_json(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_HTML rc += raptor_init_serializer_html(world) != 0; #endif #ifdef RAPTOR_SERIALIZER_NQUADS rc += raptor_init_serializer_nquads(world) != 0; #endif return rc; } /* * raptor_serializers_finish - delete all the registered serializers */ void raptor_serializers_finish(raptor_world* world) { if(world->serializers) { raptor_free_sequence(world->serializers); world->serializers = NULL; } } /* * raptor_serializer_register_factory: * @world: raptor_world object * @name: the short syntax name * @label: readable label for syntax * @mime_type: MIME type of the syntax generated by the serializer (or NULL) * @uri_string: URI string of the syntax (or NULL) * @factory: pointer to function to call to register the factory * * INTERNAL - Register a syntax that can be generated by a serializer factory * * Return value: non-0 on failure **/ RAPTOR_EXTERN_C raptor_serializer_factory* raptor_serializer_register_factory(raptor_world* world, int (*factory) (raptor_serializer_factory*)) { raptor_serializer_factory *serializer; serializer = RAPTOR_CALLOC(raptor_serializer_factory*, 1, sizeof(*serializer)); if(!serializer) return NULL; serializer->world = world; serializer->desc.mime_types = NULL; if(raptor_sequence_push(world->serializers, serializer)) return NULL; /* on error, serializer is already freed by the sequence */ /* Call the serializer registration function on the new object */ if(factory(serializer)) return NULL; /* serializer is owned and freed by the serializers sequence */ if(raptor_syntax_description_validate(&serializer->desc)) { raptor_log_error(world, RAPTOR_LOG_LEVEL_ERROR, NULL, "Serializer description failed to validate\n"); goto tidy; } #if defined(RAPTOR_DEBUG) && RAPTOR_DEBUG > 1 RAPTOR_DEBUG2("Registered serializer %s\n", serializer->desc.names[0]); #endif return serializer; /* Clean up on failure */ tidy: raptor_free_serializer_factory(serializer); return NULL; } /** * raptor_get_serializer_factory: * @world: raptor_world object * @name: the factory name or NULL for the default factory * * Get a serializer factory by name. * * Return value: the factory object or NULL if there is no such factory **/ static raptor_serializer_factory* raptor_get_serializer_factory(raptor_world* world, const char *name) { raptor_serializer_factory *factory = NULL; RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, NULL); raptor_world_open(world); /* return 1st serializer if no particular one wanted - why? */ if(!name) { factory = (raptor_serializer_factory *)raptor_sequence_get_at(world->serializers, 0); if(!factory) { RAPTOR_DEBUG1("No (default) serializers registered\n"); return NULL; } } else { int i; for(i = 0; (factory = (raptor_serializer_factory*)raptor_sequence_get_at(world->serializers, i)); i++) { int namei; const char* fname; for(namei = 0; (fname = factory->desc.names[namei]); namei++) { if(!strcmp(fname, name)) break; } if(fname) break; } } return factory; } /** * raptor_world_get_serializers_count: * @world: world object * * Get number of serializers * * Return value: number of serializers or <0 on failure **/ int raptor_world_get_serializers_count(raptor_world* world) { RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, -1); raptor_world_open(world); return raptor_sequence_size(world->serializers); } /** * raptor_world_get_serializer_description: * @world: world object * @counter: index into the list of serializers * * Get serializer descriptive syntax information * * Return value: description or NULL if counter is out of range **/ const raptor_syntax_description* raptor_world_get_serializer_description(raptor_world* world, unsigned int counter) { raptor_serializer_factory *factory; RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, NULL); raptor_world_open(world); factory = (raptor_serializer_factory*)raptor_sequence_get_at(world->serializers, counter); if(!factory) return NULL; return &factory->desc; } /** * raptor_world_is_serializer_name: * @world: raptor_world object * @name: the syntax name * * Check name of a serializer. * * Return value: non 0 if name is a known syntax name */ int raptor_world_is_serializer_name(raptor_world* world, const char *name) { if(!name) return 0; RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, 0); raptor_world_open(world); return (raptor_get_serializer_factory(world, name) != NULL); } /** * raptor_new_serializer: * @world: raptor_world object * @name: the serializer name or NULL for default syntax * * Constructor - create a new raptor_serializer object. * * Return value: a new #raptor_serializer object or NULL on failure */ raptor_serializer* raptor_new_serializer(raptor_world* world, const char *name) { raptor_serializer_factory* factory; raptor_serializer* rdf_serializer; RAPTOR_CHECK_CONSTRUCTOR_WORLD(world); raptor_world_open(world); factory = raptor_get_serializer_factory(world, name); if(!factory) return NULL; rdf_serializer = RAPTOR_CALLOC(raptor_serializer*, 1, sizeof(*rdf_serializer)); if(!rdf_serializer) return NULL; rdf_serializer->world = world; rdf_serializer->context = RAPTOR_CALLOC(void*, 1, factory->context_length); if(!rdf_serializer->context) { raptor_free_serializer(rdf_serializer); return NULL; } rdf_serializer->factory = factory; raptor_object_options_init(&rdf_serializer->options, RAPTOR_OPTION_AREA_SERIALIZER); if(factory->init(rdf_serializer, name)) { raptor_free_serializer(rdf_serializer); return NULL; } return rdf_serializer; } /** * raptor_serializer_start_to_iostream: * @rdf_serializer: the #raptor_serializer * @uri: base URI or NULL if no base URI is required * @iostream: #raptor_iostream to write serialization to * * Start serialization to an iostream with given base URI * * The passed in @iostream does not become owned by the serializer * and can be used by the caller after serializing is done. It * must be destroyed by the caller. * * Return value: non-0 on failure. **/ int raptor_serializer_start_to_iostream(raptor_serializer *rdf_serializer, raptor_uri *uri, raptor_iostream *iostream) { if(rdf_serializer->base_uri) raptor_free_uri(rdf_serializer->base_uri); if(!iostream) return 1; if(uri) uri = raptor_uri_copy(uri); rdf_serializer->base_uri = uri; rdf_serializer->locator.uri = uri; rdf_serializer->locator.line = rdf_serializer->locator.column = 0; rdf_serializer->iostream = iostream; rdf_serializer->free_iostream_on_end = 0; if(rdf_serializer->factory->serialize_start) return rdf_serializer->factory->serialize_start(rdf_serializer); return 0; } /** * raptor_serializer_start_to_filename: * @rdf_serializer: the #raptor_serializer * @filename: filename to serialize to * * Start serializing to a filename. * * Return value: non-0 on failure. **/ int raptor_serializer_start_to_filename(raptor_serializer *rdf_serializer, const char *filename) { unsigned char *uri_string = raptor_uri_filename_to_uri_string(filename); if(!uri_string) return 1; if(rdf_serializer->base_uri) raptor_free_uri(rdf_serializer->base_uri); rdf_serializer->base_uri = raptor_new_uri(rdf_serializer->world, uri_string); rdf_serializer->locator.uri = rdf_serializer->base_uri; rdf_serializer->locator.line = rdf_serializer->locator.column = 0; RAPTOR_FREE(char*, uri_string); rdf_serializer->iostream = raptor_new_iostream_to_filename(rdf_serializer->world, filename); if(!rdf_serializer->iostream) return 1; rdf_serializer->free_iostream_on_end = 1; if(rdf_serializer->factory->serialize_start) return rdf_serializer->factory->serialize_start(rdf_serializer); return 0; } /** * raptor_serializer_start_to_string: * @rdf_serializer: the #raptor_serializer * @uri: base URI or NULL if no base URI is required * @string_p: pointer to location to hold string * @length_p: pointer to location to hold length of string (or NULL) * * Start serializing to a string. * * Return value: non-0 on failure. **/ int raptor_serializer_start_to_string(raptor_serializer *rdf_serializer, raptor_uri *uri, void **string_p, size_t *length_p) { if(rdf_serializer->base_uri) raptor_free_uri(rdf_serializer->base_uri); if(uri) rdf_serializer->base_uri = raptor_uri_copy(uri); else rdf_serializer->base_uri = NULL; rdf_serializer->locator.uri = rdf_serializer->base_uri; rdf_serializer->locator.line = rdf_serializer->locator.column = 0; rdf_serializer->iostream = raptor_new_iostream_to_string(rdf_serializer->world, string_p, length_p, NULL); if(!rdf_serializer->iostream) return 1; rdf_serializer->free_iostream_on_end = 1; if(rdf_serializer->factory->serialize_start) return rdf_serializer->factory->serialize_start(rdf_serializer); return 0; } /** * raptor_serializer_start_to_file_handle: * @rdf_serializer: the #raptor_serializer * @uri: base URI or NULL if no base URI is required * @fh: FILE* to serialize to * * Start serializing to a FILE*. * * NOTE: This does not fclose the handle when it is finished. * * Return value: non-0 on failure. **/ int raptor_serializer_start_to_file_handle(raptor_serializer *rdf_serializer, raptor_uri *uri, FILE *fh) { if(rdf_serializer->base_uri) raptor_free_uri(rdf_serializer->base_uri); if(uri) rdf_serializer->base_uri = raptor_uri_copy(uri); else rdf_serializer->base_uri = NULL; rdf_serializer->locator.uri = rdf_serializer->base_uri; rdf_serializer->locator.line = rdf_serializer->locator.column = 0; rdf_serializer->iostream = raptor_new_iostream_to_file_handle(rdf_serializer->world, fh); if(!rdf_serializer->iostream) return 1; rdf_serializer->free_iostream_on_end = 1; if(rdf_serializer->factory->serialize_start) return rdf_serializer->factory->serialize_start(rdf_serializer); return 0; } /** * raptor_serializer_set_namespace: * @rdf_serializer: the #raptor_serializer * @uri: #raptor_uri of namespace or NULL * @prefix: prefix to use or NULL * * set a namespace uri/prefix mapping for serializing. * * return value: non-0 on failure. **/ int raptor_serializer_set_namespace(raptor_serializer* rdf_serializer, raptor_uri *uri, const unsigned char *prefix) { if(prefix && !*prefix) prefix = NULL; if(rdf_serializer->factory->declare_namespace) return rdf_serializer->factory->declare_namespace(rdf_serializer, uri, prefix); return 1; } /** * raptor_serializer_set_namespace_from_namespace: * @rdf_serializer: the #raptor_serializer * @nspace: #raptor_namespace to set * * Set a namespace uri/prefix mapping for serializing from an existing namespace. * * Return value: non-0 on failure. **/ int raptor_serializer_set_namespace_from_namespace(raptor_serializer* rdf_serializer, raptor_namespace *nspace) { if(rdf_serializer->factory->declare_namespace_from_namespace) return rdf_serializer->factory->declare_namespace_from_namespace(rdf_serializer, nspace); else if(rdf_serializer->factory->declare_namespace) return rdf_serializer->factory->declare_namespace(rdf_serializer, raptor_namespace_get_uri(nspace), raptor_namespace_get_prefix(nspace)); return 1; } /** * raptor_serializer_serialize_statement: * @rdf_serializer: the #raptor_serializer * @statement: #raptor_statement to serialize to a syntax * * Serialize a statement. * * Return value: non-0 on failure. **/ int raptor_serializer_serialize_statement(raptor_serializer* rdf_serializer, raptor_statement *statement) { if(!rdf_serializer->iostream) return 1; return rdf_serializer->factory->serialize_statement(rdf_serializer, statement); } /** * raptor_serializer_serialize_end: * @rdf_serializer: the #raptor_serializer * * End a serialization. * * Return value: non-0 on failure. **/ int raptor_serializer_serialize_end(raptor_serializer *rdf_serializer) { int rc; if(!rdf_serializer->iostream) return 1; if(rdf_serializer->factory->serialize_end) rc = rdf_serializer->factory->serialize_end(rdf_serializer); else rc = 0; if(rdf_serializer->iostream) { if(rdf_serializer->free_iostream_on_end) raptor_free_iostream(rdf_serializer->iostream); rdf_serializer->iostream = NULL; } return rc; } /** * raptor_free_serializer: * @rdf_serializer: #raptor_serializer object * * Destructor - destroy a raptor_serializer object. * **/ void raptor_free_serializer(raptor_serializer* rdf_serializer) { if(!rdf_serializer) return; if(rdf_serializer->factory) rdf_serializer->factory->terminate(rdf_serializer); if(rdf_serializer->context) RAPTOR_FREE(raptor_serializer_context, rdf_serializer->context); if(rdf_serializer->base_uri) raptor_free_uri(rdf_serializer->base_uri); raptor_object_options_clear(&rdf_serializer->options); RAPTOR_FREE(raptor_serializer, rdf_serializer); } /** * raptor_serializer_get_iostream: * @serializer: #raptor_serializer object * * Get the current serializer iostream. * * Return value: the serializer's current iostream or NULL if **/ raptor_iostream* raptor_serializer_get_iostream(raptor_serializer *serializer) { return serializer->iostream; } /** * raptor_serializer_set_option: * @serializer: #raptor_serializer serializer object * @option: option to set from enumerated #raptor_option values * @string: string option value (or NULL) * @integer: integer option value * * Set serializer option. * * If @string is not NULL and the option type is numeric, the string * value is converted to an integer and used in preference to @integer. * * If @string is NULL and the option type is not numeric, an error is * returned. * * The @string values used are copied. * * The allowed options are available via * raptor_world_get_option_description(). * * Return value: non 0 on failure or if the option is unknown **/ int raptor_serializer_set_option(raptor_serializer *serializer, raptor_option option, const char* string, int integer) { return raptor_object_options_set_option(&serializer->options, option, string, integer); } /** * raptor_serializer_get_option: * @serializer: #raptor_serializer serializer object * @option: option to get value * @string_p: pointer to where to store string value * @integer_p: pointer to where to store integer value * * Get serializer option. * * Any string value returned in *@string_p is shared and must * be copied by the caller. * * The allowed options are available via * raptor_world_get_option_description(). * * Return value: option value or < 0 for an illegal option **/ int raptor_serializer_get_option(raptor_serializer *serializer, raptor_option option, char** string_p, int* integer_p) { return raptor_object_options_get_option(&serializer->options, option, string_p, integer_p); } /** * raptor_serializer_get_locator: * @rdf_serializer: raptor serializer * * Get the serializer raptor locator object. * * Return value: raptor locator **/ raptor_locator* raptor_serializer_get_locator(raptor_serializer *rdf_serializer) { return &rdf_serializer->locator; } /** * raptor_serializer_get_world: * @rdf_serializer: raptor serializer * * Get the #raptor_world object associated with a serializer. * * Return value: raptor_world* pointer **/ raptor_world * raptor_serializer_get_world(raptor_serializer* rdf_serializer) { return rdf_serializer->world; } /** * raptor_serializer_get_description: * @rdf_serializer: #raptor_serializer serializer object * * Get description of the syntaxes of the serializer. * * The returned description is static and lives as long as the raptor * library (raptor world). * * Return value: description of syntax **/ const raptor_syntax_description* raptor_serializer_get_description(raptor_serializer *rdf_serializer) { return &rdf_serializer->factory->desc; } /** * raptor_serializer_flush: * @rdf_serializer: raptor serializer * * Flush the current serializer output and free any pending state * * In serializers that can generate blocks of content, this causes * the writing of any current pending block. For example in Turtle * this may write all pending triples. * * Return value: non-0 on failure **/ int raptor_serializer_flush(raptor_serializer *rdf_serializer) { int rc; if(rdf_serializer->factory->serialize_flush) rc = rdf_serializer->factory->serialize_flush(rdf_serializer); else rc = 0; return rc; }