Exemple #1
0
void
raptor_log_error_varargs(raptor_log_level level,
                         raptor_message_handler handler, void* handler_data,
                         raptor_locator* locator,
                         const char* message, va_list arguments)
{
  char *buffer;
  size_t length;
  
  if(level == RAPTOR_LOG_LEVEL_NONE)
    return;

  buffer=raptor_vsnprintf(message, arguments);
  if(!buffer) {
    if(locator) {
      raptor_print_locator(stderr, locator);
      fputc(' ', stderr);
    }
    fputs("raptor ", stderr);
    fputs(raptor_log_level_labels[level], stderr);
    fputs(" - ", stderr);
    vfprintf(stderr, message, arguments);
    fputc('\n', stderr);
    return;
  }

  length=strlen(buffer);
  if(buffer[length-1]=='\n')
    buffer[length-1]='\0';
  
  raptor_log_error(level, handler, handler_data, locator, buffer);

  RAPTOR_FREE(cstring, buffer);
}
void
raptor_log_error_varargs(raptor_world* world, raptor_log_level level,
                         raptor_locator* locator,
                         const char* message, va_list arguments)
{
  char *buffer = NULL;
  size_t length;
  
  if(level == RAPTOR_LOG_LEVEL_NONE)
    return;

  if(world->internal_ignore_errors)
    return;

  length = raptor_vasprintf(&buffer, message, arguments);
  if(!buffer) {
    if(locator && world) {
      raptor_locator_print(locator, stderr);
      fputc(' ', stderr);
    }
    fputs("raptor ", stderr);
    fputs(raptor_log_level_labels[level], stderr);
    fputs(" - ", stderr);
    vfprintf(stderr, message, arguments);
    fputc('\n', stderr);
    return;
  }

  if(length >= 1 && buffer[length-1] == '\n')
    buffer[length-1]='\0';
  
  raptor_log_error(world, level, locator, buffer);

  RAPTOR_FREE(char*, buffer);
}
Exemple #3
0
/* internal */
void
raptor_log_error_to_handlers(raptor_error_handlers* error_handlers,
                             raptor_log_level level,
                             raptor_locator* locator, const char* message)
{
  if(level == RAPTOR_LOG_LEVEL_NONE)
    return;

  raptor_log_error(level, error_handlers->handlers[level].handler,
                   error_handlers->handlers[level].user_data,
                   locator, message);
}
Exemple #4
0
/**
 * raptor_sax2_parse_chunk:
 * @sax2: sax2 object
 * @buffer: input buffer
 * @len: input buffer lenght
 * @is_end: non-0 if end of data
 *
 * Parse a chunk of XML data generating SAX2 events
 *
 * Return value: non-0 on failure
 */
int
raptor_sax2_parse_chunk(raptor_sax2* sax2, const unsigned char *buffer,
                        size_t len, int is_end) 
{
#ifdef RAPTOR_XML_LIBXML
  /* parser context */
  xmlParserCtxtPtr xc = sax2->xc;
  int rc;
  
  if(!xc) {
    int libxml_options = 0;

    if(!len) {
      /* no data given at all */
      raptor_sax2_update_document_locator(sax2, sax2->locator);
      raptor_log_error(sax2->world, RAPTOR_LOG_LEVEL_ERROR, sax2->locator,
                       "XML Parsing failed - no element found");
      return 1;
    }

    xc = xmlCreatePushParserCtxt(&sax2->sax, sax2, /* user data */
                                 (char*)buffer, RAPTOR_BAD_CAST(int, len),
                                 NULL);
    if(!xc)
      goto handle_error;

#ifdef RAPTOR_LIBXML_XML_PARSE_NONET
    if(RAPTOR_OPTIONS_GET_NUMERIC(sax2, RAPTOR_OPTION_NO_NET))
      libxml_options |= XML_PARSE_NONET;
#endif
#ifdef HAVE_XMLCTXTUSEOPTIONS
    xmlCtxtUseOptions(xc, libxml_options);
#endif
    
    xc->userData = sax2; /* user data */
    xc->vctxt.userData = sax2; /* user data */
    xc->vctxt.error = (xmlValidityErrorFunc)raptor_libxml_validation_error;
    xc->vctxt.warning = (xmlValidityWarningFunc)raptor_libxml_validation_warning;
    xc->replaceEntities = 1;
    
    sax2->xc = xc;

    if(is_end)
      len = 0;
    else
      return 0;
  }
Exemple #5
0
/*
 * 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;
}
Exemple #6
0
/**
 * raptor_sax2_parse_start:
 * @sax2: sax2 object
 * @base_uri: base URI
 *
 * Start an XML SAX2 parse.
 */
void
raptor_sax2_parse_start(raptor_sax2* sax2, raptor_uri *base_uri)
{
  sax2->depth = 0;
  sax2->root_element = NULL;
  sax2->current_element = NULL;

  if(sax2->base_uri)
    raptor_free_uri(sax2->base_uri);
  if(base_uri)
    sax2->base_uri = raptor_uri_copy(base_uri);
  else
    sax2->base_uri = NULL;

#ifdef RAPTOR_XML_LIBXML
  raptor_libxml_sax_init(sax2);

#if LIBXML_VERSION < 20425
  sax2->first_read = 1;
#endif

  if(sax2->xc) {
    raptor_libxml_free(sax2->xc);
    sax2->xc = NULL;
  }
#endif

  raptor_namespaces_clear(&sax2->namespaces);

  if(raptor_namespaces_init(sax2->world, &sax2->namespaces, 1)) {
    /* log a fatal error and set sax2 to failed state
       since the function signature does not currently support returning an error */
    raptor_log_error(sax2->world, RAPTOR_LOG_LEVEL_FATAL, sax2->locator,
                     "raptor_namespaces_init() failed");
    sax2->failed = 1;
  }
}
Exemple #7
0
static void 
raptor_libxml_xmlStructuredError_handler_common(raptor_world *world,
                                                raptor_locator *locator,
                                                xmlErrorPtr err)
{
  raptor_stringbuffer* sb;
  char *nmsg;
  raptor_log_level level = RAPTOR_LOG_LEVEL_ERROR;

  if(err == NULL || err->code == XML_ERR_OK || err->level == XML_ERR_NONE)
    return;

  /* Do not warn about things with no location */
  if(err->level == XML_ERR_WARNING && !err->file)
    return;

  /* XML fatal errors never cause an abort */
  if(err->level == XML_ERR_FATAL)
    err->level = XML_ERR_ERROR;
  

  sb = raptor_new_stringbuffer();
  if(err->domain != XML_FROM_HTML)
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)"XML ",
                                              4, 1);
  
  if(err->domain != XML_FROM_NONE && err->domain < XML_LAST_DL) {
    const unsigned char* label;
    label = (const unsigned char*)raptor_libxml_domain_labels[(int)err->domain];
    raptor_stringbuffer_append_string(sb, label, 1);
    raptor_stringbuffer_append_counted_string(sb, 
                                              (const unsigned char*)" ", 1, 1);
  }
  
  if(err->level == XML_ERR_WARNING)
    raptor_stringbuffer_append_counted_string(sb, 
                                              (const unsigned char*)"warning: ", 
                                              9, 1);
  else /*  XML_ERR_ERROR or XML_ERR_FATAL */
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)"error: ", 
                                              7, 1);
  
  if(err->message) {
    unsigned char* msg;
    size_t len;
    msg = (unsigned char*)err->message;
    len= strlen((const char*)msg);
    if(len && msg[len-1] == '\n')
      msg[--len]='\0';
    
    raptor_stringbuffer_append_counted_string(sb, msg, len, 1);
  }

#if LIBXML_VERSION >= 20618
  /* 2005-02-13 - v2.6.18 */

  /* str1 has the detailed HTTP error */
  if(err->domain == XML_FROM_HTTP && err->str1) {
    unsigned char* msg;
    size_t len;
    msg = (unsigned char*)err->str1;
    len= strlen((const char*)msg);
    if(len && msg[len-1] == '\n')
      msg[--len]='\0';
    
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)" - ",
                                              3, 1);
    raptor_stringbuffer_append_counted_string(sb, msg, len, 1);
  }
#endif
  
  /* When err->domain == XML_FROM_XPATH then err->int1 is
   * the offset into err->str1, the line with the error
   */
  if(err->domain == XML_FROM_XPATH && err->str1) {
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)" in ",
                                              4, 1);
    raptor_stringbuffer_append_string(sb, (const unsigned char*)err->str1, 1);
  }

  nmsg = (char*)raptor_stringbuffer_as_string(sb);
  if(err->level == XML_ERR_FATAL)
    level = RAPTOR_LOG_LEVEL_FATAL;
  else if(err->level == XML_ERR_ERROR)
    level = RAPTOR_LOG_LEVEL_ERROR;
  else
    level = RAPTOR_LOG_LEVEL_WARN;

  raptor_log_error(world, level, locator, nmsg);
  
  raptor_free_stringbuffer(sb);
}
Exemple #8
0
void 
raptor_libxml_xmlStructuredErrorFunc(void *user_data, xmlErrorPtr err)
{
  raptor_error_handlers* error_handlers=(raptor_error_handlers*)user_data;
  raptor_stringbuffer* sb;
  char *nmsg;
  raptor_message_handler handler=NULL;
  void* handler_data=NULL;
  raptor_log_level level=RAPTOR_LOG_LEVEL_ERROR;
  
  if(err == NULL || err->code == XML_ERR_OK || err->level == XML_ERR_NONE)
    return;

  /* Do not warn about things with no location */
  if(err->level == XML_ERR_WARNING && !err->file)
    return;

  /* XML fatal errors never cause an abort */
  if(err->level == XML_ERR_FATAL)
    err->level= XML_ERR_ERROR;
  
  
  sb=raptor_new_stringbuffer();
  if(err->domain != XML_FROM_HTML)
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)"XML ",
                                              4, 1);
  
  if(err->domain != XML_FROM_NONE && err->domain < XML_LAST_DL) {
    const unsigned char* label;
    label=(const unsigned char*)raptor_libxml_domain_labels[(int)err->domain];
    raptor_stringbuffer_append_string(sb, label, 1);
    raptor_stringbuffer_append_counted_string(sb, 
                                              (const unsigned char*)" ", 1, 1);
  }
  
  if(err->level == XML_ERR_WARNING)
    raptor_stringbuffer_append_counted_string(sb, 
                                              (const unsigned char*)"warning: ", 
                                              9, 1);
  else /*  XML_ERR_ERROR or XML_ERR_FATAL */
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)"error: ", 
                                              7, 1);
  
  if(err->message) {
    unsigned char* msg;
    size_t len;
    msg=(unsigned char*)err->message;
    len= strlen((const char*)msg);
    if(len && msg[len-1] == '\n')
      msg[--len]='\0';
    
    raptor_stringbuffer_append_counted_string(sb, msg, len, 1);
  }

#if LIBXML_VERSION >= 20618
  /* 2005-02-13 - v2.6.18 */

  /* str1 has the detailed HTTP error */
  if(err->domain == XML_FROM_HTTP && err->str1) {
    unsigned char* msg;
    size_t len;
    msg=(unsigned char*)err->str1;
    len= strlen((const char*)msg);
    if(len && msg[len-1] == '\n')
      msg[--len]='\0';
    
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)" - ",
                                              3, 1);
    raptor_stringbuffer_append_counted_string(sb, msg, len, 1);
  }
#endif
  
  /* When err->domain == XML_FROM_XPATH then err->int1 is
   * the offset into err->str1, the line with the error
   */
  if(err->domain == XML_FROM_XPATH && err->str1) {
    raptor_stringbuffer_append_counted_string(sb, (const unsigned char*)" in ",
                                              4, 1);
    raptor_stringbuffer_append_string(sb, (const unsigned char*)err->str1, 1);
  }

  if(error_handlers) {
    if(error_handlers->magic != RAPTOR_ERROR_HANDLER_MAGIC) {
#ifdef RAPTOR_DEBUG
      if(1) /* FIXME */
        RAPTOR_DEBUG2("Received bogus error_handlers pointer %p\n",
                      error_handlers);
        else
          RAPTOR_FATAL2("Received bogus error_handlers pointer %p\n",
                        error_handlers);
#endif
      error_handlers=NULL;
    }
  }
  
  nmsg=(char*)raptor_stringbuffer_as_string(sb);
  if(err->level == XML_ERR_FATAL)
    level=RAPTOR_LOG_LEVEL_FATAL;
  else if(err->level == XML_ERR_ERROR)
    level=RAPTOR_LOG_LEVEL_ERROR;
  else
    level=RAPTOR_LOG_LEVEL_WARNING;

  if(error_handlers && level <= error_handlers->last_log_level) {
    handler=error_handlers->handlers[level].handler;
    handler_data=error_handlers->handlers[level].user_data;
  }

  raptor_log_error(level, handler, handler_data,
                   (error_handlers ? error_handlers->locator : NULL),
                   nmsg);

  
  raptor_free_stringbuffer(sb);
}
/*
 * raptor_turtle_emit_subject_collection_items:
 * @serializer: #raptor_serializer object
 * @subject: subject node
 * @depth: depth into tree
 * 
 * Emit an abbreviated rdf collection of items (rdf:first, rdf:rest) about a subject node.
 * 
 * Return value: non-0 on failure
 **/
static int
raptor_turtle_emit_subject_collection_items(raptor_serializer* serializer,
                                            raptor_abbrev_subject* subject,
                                            int depth)
{
  raptor_turtle_context* context = (raptor_turtle_context*)serializer->context;
  int rv = 0;
  raptor_avltree_iterator* iter = NULL;
  int i;
  int is_new_subject = 0;

  RAPTOR_DEBUG5("Emitting subject collection items for node %p refcount %d subject %d object %d\n", 
                subject->node,
                subject->node->ref_count, subject->node->count_as_subject, 
                subject->node->count_as_object);

  /* if just saw a new subject (is_new_subject is true) then there is no need
   * to advance the iterator - it was just reset
   */
  for(i = 0, (iter = raptor_new_avltree_iterator(subject->properties, NULL, NULL, 1));
      iter && !rv;
      i++, (rv = is_new_subject ? 0 : raptor_avltree_iterator_next(iter))) {
    raptor_abbrev_node** nodes;
    raptor_abbrev_node* predicate;
    raptor_abbrev_node* object;

    is_new_subject = 0;

    nodes = (raptor_abbrev_node**)raptor_avltree_iterator_get(iter);
    if(!nodes)
      break;
    predicate= nodes[0];
    object= nodes[1];
    
    if(!raptor_uri_equals(predicate->term->value.uri,
                          context->rdf_first_uri)) {
      raptor_log_error(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                       "Malformed collection - first predicate is not rdf:first");
      return 1;
    }
    
    if(!object)
      continue;
    
    if(i > 0)
      raptor_turtle_writer_newline(context->turtle_writer);
    
    switch(object->term->type) {
      case RAPTOR_TERM_TYPE_URI:
        rv = raptor_turtle_emit_resource(serializer, object, depth+1);
        break;
          
      case RAPTOR_TERM_TYPE_LITERAL:
        rv = raptor_turtle_emit_literal(serializer, object, depth+1);
        break;
          
      case RAPTOR_TERM_TYPE_BLANK:
        rv = raptor_turtle_emit_blank(serializer, object, depth+1);
        break;

      case RAPTOR_TERM_TYPE_UNKNOWN:
      default:
        raptor_log_error_formatted(serializer->world, RAPTOR_LOG_LEVEL_ERROR,
                                   NULL, "Triple has unsupported term type %d", 
                                   object->term->type);
        break;
    }

    /* Return error if emitting something failed above */
    if(rv)
      return rv;

    /* last item */
    rv = raptor_avltree_iterator_next(iter);
    if(rv)
      break;

    nodes = (raptor_abbrev_node**)raptor_avltree_iterator_get(iter);
    predicate = nodes[0];
    object = nodes[1];

    if(!raptor_uri_equals(predicate->term->value.uri, context->rdf_rest_uri)) {
      raptor_log_error(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                       "Malformed collection - second predicate is not rdf:rest");
      return 1;
    }
    
    if(object->term->type == RAPTOR_TERM_TYPE_BLANK) {
      subject = raptor_abbrev_subject_find(context->blanks, object->term);

      if(!subject) {
        raptor_log_error(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                         "Malformed collection - could not find subject for rdf:rest");
        return 1;
      }

      /* got a <(old)subject> rdf:rest <(new)subject> triple so know
       * subject has changed and should reset the properties iterator
       */
      if(iter)
        raptor_free_avltree_iterator(iter);
      iter = raptor_new_avltree_iterator(subject->properties, NULL, NULL, 1);
      is_new_subject = 1;

    } else {
      if(object->term->type != RAPTOR_TERM_TYPE_URI ||
         !raptor_uri_equals(object->term->value.uri, context->rdf_nil_uri)) {
        raptor_log_error(serializer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                         "Malformed collection - last rdf:rest resource is not rdf:nil");
        return 1;
      }
      break;
    }
  }
  if(iter)
    raptor_free_avltree_iterator(iter);
  
  return rv;
}
Exemple #10
0
/**
 * raptor_turtle_writer_literal:
 * @turtle_writer: Turtle writer object
 * @nstack: Namespace stack for making a QName for datatype URI
 * @s: literal string to write (SHARED)
 * @lang: language tag (may be NULL)
 * @datatype: datatype URI (may be NULL)
 *
 * Write a literal (possibly with lang and datatype) to the Turtle writer.
 *
 * Return value: non-0 on failure
 **/
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)
{
  /* DBL_MAX = 309 decimal digits */
  #define INT_MAX_LEN 309 

  /* DBL_EPSILON = 52 digits */
  #define FRAC_MAX_LEN 52

  char* endptr = (char *)s;
  int written = 0;

  /* typed literal special cases */
  if(datatype) {
    /* integer */
    if(raptor_uri_equals(datatype, turtle_writer->xsd_integer_uri)) {
      /* FIXME. Work around that gcc < 4.5 cannot disable warn_unused_result */
      long gcc_is_stupid = strtol((const char*)s, &endptr, 10);
      if(endptr != (char*)s && !*endptr) {
        raptor_iostream_string_write(s, turtle_writer->iostr);
        /* More gcc madness to 'use' the variable I didn't want */
        written = 1 + 0 * (int)gcc_is_stupid;
      } else {
        raptor_log_error(turtle_writer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                         "Illegal value for xsd:integer literal.");
      }

    /* double, decimal */
    } else if(raptor_uri_equals(datatype, turtle_writer->xsd_double_uri) ||
      raptor_uri_equals(datatype, turtle_writer->xsd_decimal_uri)) {
      /* FIXME. Work around that gcc < 4.5 cannot disable warn_unused_result */
      double gcc_is_doubly_stupid = strtod((const char*)s, &endptr);
      if(endptr != (char*)s && !*endptr) {
        raptor_iostream_string_write(s, turtle_writer->iostr);
        /* More gcc madness to 'use' the variable I didn't want */
        written = 1 +  0 * (int)gcc_is_doubly_stupid;
      } else {
        raptor_log_error(turtle_writer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                         "Illegal value for xsd:double or xsd:decimal literal.");
      }

    /* boolean */
    } else if(raptor_uri_equals(datatype, turtle_writer->xsd_boolean_uri)) {
      if(!strcmp((const char*)s, "0") || !strcmp((const char*)s, "false")) {
        raptor_iostream_string_write("false", turtle_writer->iostr);
        written = 1;
      } else if(!strcmp((const char*)s, "1") || !strcmp((const char*)s, "true")) {
        raptor_iostream_string_write("true", turtle_writer->iostr);
        written = 1;
      } else {
        raptor_log_error(turtle_writer->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                         "Illegal value for xsd:boolean literal.");
      }
    }
  }

  if(written)
    return 0;
    
  if(raptor_turtle_writer_quoted_counted_string(turtle_writer, s,
                                                strlen((const char*)s)))
    return 1;

  /* typed literal, not a special case */
  if(datatype) {
    raptor_qname* qname;

    raptor_iostream_string_write("^^", turtle_writer->iostr);
    qname = raptor_new_qname_from_namespace_uri(nstack, datatype, 10);
    if(qname) {
      raptor_turtle_writer_qname(turtle_writer, qname);
      raptor_free_qname(qname);
    } else
      raptor_turtle_writer_reference(turtle_writer, datatype);
  } else if(lang) {
    /* literal with language tag */
    raptor_iostream_write_byte('@', turtle_writer->iostr);
    raptor_iostream_string_write(lang, turtle_writer->iostr);
  }

  return 0;
}
Exemple #11
0
/**
 * raptor_xml_escape_string_any:
 * @world: raptor world
 * @string: string to XML escape (UTF-8)
 * @len: length of string
 * @buffer: the buffer to use for new string (UTF-8) or NULL to just calculate expected length
 * @length: buffer size
 * @quote: optional quote character to escape for attribute content, or 0
 * @xml_version: XML 1.0 (10) or XML 1.1 (11)
 *
 * Return an XML-escaped version a string.
 * 
 * Follows
 * <ulink url="http://www.w3.org/TR/xml-c14n#ProcessingModel">Canonical XML rules on Text Nodes and Attribute Nodes</ulink>
 *
 * Both:
 *   Replaces <literal>&amp;</literal> and <literal>&lt;</literal>
 *   with <literal>&amp;amp;</literal> and <literal>&amp;lt;</literal>
 * respectively, preserving other characters.
 * 
 * Text Nodes:
 *   <literal>&gt;</literal> is turned into <literal>&amp;gt;</literal>
 *   ##xD is turned into <literal>&amp;##xD;</literal>
 *
 * Attribute Nodes:
 *   <literal>&gt;</literal> is generated not <literal>&amp;gt</literal>.
 *   ##x9, ##xA and ##xD are turned into
 *   <literal>&amp;##x9;</literal>,
 *   <literal>&amp;##xA;</literal> and
 *   <literal>&amp;##xD;</literal>
 *   entities.
 *
 * If @quote is given it can be either of '\'' or '\"'
 * which will be turned into <literal>&amp;apos;</literal> or
 * <literal>&amp;quot;</literal> respectively.
 * ASCII NUL ('\0') or any other character will not be escaped.
 * 
 * If @buffer is NULL, no work is done but the size of buffer
 * required is returned.  The output in buffer remains in UTF-8.
 *
 * If the input @string is empty, a single NUL will be written to the
 * buffer.
 *
 * Return value: the number of bytes required / used or <0 on failure.
 **/
int
raptor_xml_escape_string_any(raptor_world *world,
                             const unsigned char *string, size_t len,
                             unsigned char *buffer, size_t length,
                             char quote,
                             int xml_version)
{
  size_t l;
  size_t new_len = 0;
  const unsigned char *p;
  unsigned char *q;
  int unichar_len;
  raptor_unichar unichar;

  if(!string)
    return -1;
  
  RAPTOR_ASSERT_OBJECT_POINTER_RETURN_VALUE(world, raptor_world, -1);

  raptor_world_open(world);

  if(quote != '\"' && quote != '\'')
    quote='\0';

  for(l = len, p = string; l; p++, l--) {
    if(*p > 0x7f) {
      unichar_len = raptor_unicode_utf8_string_get_char(p, l, &unichar);
      if(unichar_len < 0 || RAPTOR_GOOD_CAST(size_t, unichar_len) > l) {
        raptor_log_error(world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                         "Bad UTF-8 encoding.");
        return -1;
      }
    } else {
      unichar=*p;
      unichar_len = 1;
    }
  
    if(unichar == '&')
      /* &amp; */
      new_len+= 5;
    else if(unichar == '<' || (!quote && unichar == '>'))
      /* &lt; or &gt; */
      new_len+= 4;
    else if(quote && unichar == (unsigned long)quote)
      /* &apos; or &quot; */
      new_len+= 6;
    else if(unichar == 0x0d ||
             (quote && (unichar == 0x09 || unichar == 0x0a)))
      /* &#xD; or &#x9; or &xA; */
      new_len+= 5;
    else if(unichar == 0x7f ||
             (unichar < 0x20 && unichar != 0x09 && unichar != 0x0a)) {
      if(!unichar || xml_version < 11) {
        raptor_log_error_formatted(world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                                   "Cannot write illegal XML 1.0 character U+%6lX.",
                                   unichar);
      } else {
        /* &#xX; */
        new_len+= 5;
        if(unichar > 0x0f)
          new_len++;
      }
    } else
      new_len+= unichar_len;

    unichar_len--; /* since loop does len-- */
    p += unichar_len; l -= unichar_len;
  }

  if(length && new_len > length)
    return 0;

  if(!buffer)
    return RAPTOR_BAD_CAST(int, new_len);
  
  for(l = len, p = string, q = buffer; l; p++, l--) {
    if(*p > 0x7f) {
      unichar_len = raptor_unicode_utf8_string_get_char(p, l, &unichar);
      /* if the UTF-8 encoding is bad, we already did return -1 above */
    } else {
      unichar=*p;
      unichar_len = 1;
    }

    if(unichar == '&') {
      memcpy(q, "&amp;", 5);
      q+= 5;
    } else if(unichar == '<') {
      memcpy(q, "&lt;", 4);
      q+= 4;
    } else if(!quote && unichar == '>') {
      memcpy(q, "&gt;", 4);
      q+= 4;
    } else if(quote && unichar == (unsigned long)quote) {
      if(quote == '\'')  
        memcpy(q, "&apos;", 6);
      else
        memcpy(q, "&quot;", 6);
      q+= 6;
    } else if(unichar == 0x0d ||
               (quote && (unichar == 0x09 || unichar == 0x0a))) {
      /* &#xX; */
      *q++='&';
      *q++='#';
      *q++='x';
      if(unichar == 0x09)
        *q++ = '9';
      else
        *q++ = 'A'+ ((char)unichar-0x0a);
      *q++= ';';
    } else if(unichar == 0x7f ||
               (unichar < 0x20 && unichar != 0x09 && unichar != 0x0a)) {
      if(!unichar || xml_version < 11) {
        raptor_log_error_formatted(world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                                   "Cannot write illegal XML 1.0 character U+%6lX.",
                                   unichar);
      } else {
        /* &#xX; */
        *q++ = '&';
        *q++ = '#';
        *q++ = 'x';
        q += raptor_format_integer((char*)q, 3, 
                                   RAPTOR_GOOD_CAST(unsigned int, unichar), 
                                   /* base */ 16, -1, '\0');
        *q++ = ';';
      }
    } else {
      /* coverity[negative_returns]
       * negative unichar_len values are checked and cause return -1 above */
      memcpy(q, p, unichar_len);
      q+= unichar_len;
    }

    unichar_len--; /* since loop does len-- */
    p += unichar_len; l -= unichar_len;
  }