libdap++  Updated for version 3.12.0
XMLWriter.cc
Go to the documentation of this file.
1 
2 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
3 // Access Protocol.
4 
5 // Copyright (c) 2010 OPeNDAP, Inc.
6 // Author: James Gallagher <jgallagher@opendap.org>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
23 
24 /*
25  * XMLWriter.cpp
26  *
27  * Created on: Jul 28, 2010
28  * Author: jimg
29  */
30 
31 #include "XMLWriter.h"
32 
33 #include <libxml/encoding.h>
34 #include <libxml/xmlwriter.h>
35 
36 #include <InternalErr.h>
37 
38 const char *ENCODING = "ISO-8859-1";
39 const int XML_BUF_SIZE = 2000000;
40 
41 using namespace libdap;
42 
43 XMLWriter::XMLWriter(const string &pad) {
44  LIBXML_TEST_VERSION;
45 
46  /* Create a new XML buffer, to which the XML document will be
47  * written */
48  try {
49  if (!(d_doc_buf = xmlBufferCreateSize(XML_BUF_SIZE)))
50  throw InternalErr(__FILE__, __LINE__, "Error allocating the xml buffer");
51 
52  xmlBufferSetAllocationScheme(d_doc_buf, XML_BUFFER_ALLOC_DOUBLEIT);
53 
54  /* Create a new XmlWriter for memory, with no compression.
55  * Remark: there is no compression for this kind of xmlTextWriter */
56  if (!(d_writer = xmlNewTextWriterMemory(d_doc_buf, 0)))
57  throw InternalErr(__FILE__, __LINE__, "Error allocating memory for xml writer");
58 
59  if (xmlTextWriterSetIndent(d_writer, pad.length()) < 0)
60  throw InternalErr(__FILE__, __LINE__, "Error starting indentation for response document ");
61 
62  if (xmlTextWriterSetIndentString(d_writer, (const xmlChar*)pad.c_str()) < 0)
63  throw InternalErr(__FILE__, __LINE__, "Error setting indentation for response document ");
64 
65  d_started = true;
66  d_ended = false;
67 
68  /* Start the document with the xml default for the version,
69  * encoding ISO 8859-1 and the default for the standalone
70  * declaration. MY_ENCODING defined at top of this file*/
71  if (xmlTextWriterStartDocument(d_writer, NULL, ENCODING, NULL) < 0)
72  throw InternalErr(__FILE__, __LINE__, "Error starting xml response document");
73  }
74  catch (InternalErr &e) {
75  m_cleanup();
76  throw;
77  }
78 
79 }
80 
82  m_cleanup();
83 }
84 
85 void XMLWriter::m_cleanup() {
86  // make sure the buffer and writer are all cleaned up
87  if (d_writer) {
88  xmlFreeTextWriter(d_writer); // This frees both d_writer and d_doc_buf
89  d_writer = 0;
90  // d_doc_buf = 0;
91  }
92 
93  // We could be here because of an exception and d_writer might be zero
94  if (d_doc_buf) {
95  xmlBufferFree(d_doc_buf);
96  d_doc_buf = 0;
97  }
98 
99  d_started = false;
100  d_ended = false;
101 }
102 
103 const char *XMLWriter::get_doc() {
104  if (d_writer && d_started) {
105  if (xmlTextWriterEndDocument(d_writer) < 0)
106  throw InternalErr(__FILE__, __LINE__, "Error ending the document");
107 
108  d_ended = true;
109 
110  // must call this before getting the buffer content. Odd, but appears to be true.
111  // jhrg
112  xmlFreeTextWriter(d_writer);
113  d_writer = 0;
114  }
115 
116  if (!d_doc_buf->content)
117  throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");
118 #if 0
119  // This is not needed when the TextWriter is freed before getting buffer content.
120  if (xmlTextWriterFlush(d_writer) < 0)
121  throw InternalErr(__FILE__, __LINE__, "Error flushing the xml writer buffer");
122 #endif
123 
124  return (const char *)d_doc_buf->content;
125 }
126 
127 unsigned int XMLWriter::get_doc_size() {
128  if (d_writer && d_started) {
129  if (xmlTextWriterEndDocument(d_writer) < 0)
130  throw InternalErr(__FILE__, __LINE__, "Error ending the document");
131 
132  d_ended = true;
133 
134  // must call this before getting the buffer content. Odd, but appears to be true.
135  // jhrg
136  xmlFreeTextWriter(d_writer);
137  d_writer = 0;
138  }
139 
140  if (!d_doc_buf->content)
141  throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");
142 #if 0
143  // This is not needed when the TextWriter is freed before getting buffer content.
144  if (xmlTextWriterFlush(d_writer) < 0)
145  throw InternalErr(__FILE__, __LINE__, "Error flushing the xml writer buffer");
146 #endif
147 
148  // how much of the buffer is in use?
149  return d_doc_buf->use;
150 }