File: XMLWriter.cc

package info (click to toggle)
libdap 3.20.11-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 24,568 kB
  • sloc: cpp: 50,809; sh: 41,536; xml: 23,511; ansic: 20,030; yacc: 2,508; exp: 1,544; makefile: 990; lex: 309; perl: 52; fortran: 8
file content (144 lines) | stat: -rw-r--r-- 4,812 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2010 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library 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 library 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 library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

/*
 * XMLWriter.cpp
 *
 *  Created on: Jul 28, 2010
 *      Author: jimg
 */

#include "config.h"

#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>

#include "XMLWriter.h"
#include "InternalErr.h"

// TODO - Bite the bullet and make the encoding UTF-8 as required by dap4. This will break a lot of tests but the baselines could be amended using  a bash script and sed.
const char *ENCODING = "ISO-8859-1";
const int XML_BUF_SIZE = 2000000;

using namespace libdap;

XMLWriter::XMLWriter(const string &pad) {
    // LEAK The LIBXML_TEST_VERSION macro leaks 40 bytes according to valgrind
    // on centos7. jhrg 6/19/19
    // LIBXML_TEST_VERSION;

    /* Create a new XML buffer, to which the XML document will be
     * written */
    try {
        if (!(d_doc_buf = xmlBufferCreateSize(XML_BUF_SIZE)))
            throw InternalErr(__FILE__, __LINE__, "Error allocating the xml buffer");

        xmlBufferSetAllocationScheme(d_doc_buf, XML_BUFFER_ALLOC_DOUBLEIT);

        /* Create a new XmlWriter for memory, with no compression.
         * Remark: there is no compression for this kind of xmlTextWriter */
        if (!(d_writer = xmlNewTextWriterMemory(d_doc_buf, 0)))
            throw InternalErr(__FILE__, __LINE__, "Error allocating memory for xml writer");

        if (xmlTextWriterSetIndent(d_writer, pad.length()) < 0)
            throw InternalErr(__FILE__, __LINE__, "Error starting indentation for response document ");

        if (xmlTextWriterSetIndentString(d_writer, (const xmlChar*)pad.c_str()) < 0)
            throw InternalErr(__FILE__, __LINE__, "Error setting indentation for response document ");

        d_started = true;
        d_ended = false;

        /* Start the document with the xml default for the version,
         * encoding ISO 8859-1 and the default for the standalone
         * declaration. MY_ENCODING defined at top of this file*/
        if (xmlTextWriterStartDocument(d_writer, NULL, ENCODING, NULL) < 0)
            throw InternalErr(__FILE__, __LINE__, "Error starting xml response document");
    }
    catch (InternalErr &e) {
        m_cleanup();
        throw;
    }

}

XMLWriter::~XMLWriter() {
    m_cleanup();
}

void XMLWriter::m_cleanup() {
    // make sure the buffer and writer are all cleaned up
    if (d_writer) {
        xmlFreeTextWriter(d_writer); // This frees both d_writer and d_doc_buf
        d_writer = 0;
        // d_doc_buf = 0;
    }

    // We could be here because of an exception and d_writer might be zero
    if (d_doc_buf) {
        xmlBufferFree(d_doc_buf);
        d_doc_buf = 0;
    }

    d_started = false;
    d_ended = false;
}

const char *XMLWriter::get_doc() {
    if (d_writer && d_started) {
        if (xmlTextWriterEndDocument(d_writer) < 0)
            throw InternalErr(__FILE__, __LINE__, "Error ending the document");

        d_ended = true;

        // must call this before getting the buffer content. Odd, but appears to be true.
        // jhrg
        xmlFreeTextWriter(d_writer);
        d_writer = 0;
    }

    if (!d_doc_buf->content)
        throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");

    return (const char *)d_doc_buf->content;
}

unsigned int XMLWriter::get_doc_size() {
    if (d_writer && d_started) {
        if (xmlTextWriterEndDocument(d_writer) < 0)
            throw InternalErr(__FILE__, __LINE__, "Error ending the document");

        d_ended = true;

        // must call this before getting the buffer content. Odd, but appears to be true.
        // jhrg
        xmlFreeTextWriter(d_writer);
        d_writer = 0;
    }

    if (!d_doc_buf->content)
        throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");

    // how much of the buffer is in use?
    return d_doc_buf->use;
}