rsvg-xml.c 3.27 KB
Newer Older
1 2
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 sts=4 expandtab: */
Christian Persch's avatar
Christian Persch committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright © 2010 Christian Persch
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
  
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
*/

#include "config.h"

24
#include "rsvg-private.h"
Christian Persch's avatar
Christian Persch committed
25 26 27 28 29 30 31 32 33 34
#include "rsvg-xml.h"

typedef struct {
    GInputStream *stream;
    GCancellable *cancellable;
    GError      **error;
} RsvgXmlInputStreamContext;

/* this should use gsize, but libxml2 is borked */
static int
35
context_read (void *data,
Christian Persch's avatar
Christian Persch committed
36 37 38
              char *buffer,
              int   len)
{
39
    RsvgXmlInputStreamContext *context = data;
Christian Persch's avatar
Christian Persch committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
    gssize n_read;

    if (*(context->error))
        return -1;

    n_read = g_input_stream_read (context->stream, buffer, (gsize) len,
                                  context->cancellable,
                                  context->error);
    if (n_read < 0)
        return -1;

    return (int) n_read;
}

static int
55
context_close (void *data)
Christian Persch's avatar
Christian Persch committed
56
{
57
    RsvgXmlInputStreamContext *context = data;
Christian Persch's avatar
Christian Persch committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71
    gboolean ret;

    /* Don't overwrite a previous error */
    ret = g_input_stream_close (context->stream, context->cancellable,
                                *(context->error) == NULL ? context->error : NULL);

    g_object_unref (context->stream);
    if (context->cancellable)
        g_object_unref (context->cancellable);
    g_slice_free (RsvgXmlInputStreamContext, context);

    return ret ? 0 : -1;
}

72 73 74 75 76
xmlParserCtxtPtr rsvg_create_xml_parser_from_stream (xmlSAXHandlerPtr sax,
						     void            *sax_user_data,
						     GInputStream    *stream,
						     GCancellable    *cancellable,
						     GError          **error)
Christian Persch's avatar
Christian Persch committed
77 78
{
    RsvgXmlInputStreamContext *context;
79
    xmlParserCtxtPtr parser;
Christian Persch's avatar
Christian Persch committed
80 81 82 83 84 85 86 87 88 89

    g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
    g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
    g_return_val_if_fail (error != NULL, NULL);

    context = g_slice_new (RsvgXmlInputStreamContext);
    context->stream = g_object_ref (stream);
    context->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
    context->error = error;

90 91 92 93 94 95 96 97 98 99 100 101 102 103
    parser = xmlCreateIOParserCtxt (sax,
                                    sax_user_data,
                                    context_read,
                                    context_close,
                                    context,
                                    XML_CHAR_ENCODING_NONE);

    if (!parser) {
        g_set_error (error, rsvg_error_quark (), 0, _("Error creating XML parser"));

        /* on error, xmlCreateIOParserCtxt() frees our context via the context_close function */
    }

    return parser;
Christian Persch's avatar
Christian Persch committed
104
}