Imported Upstream version 2.91.2
[platform/upstream/libxml++.git] / libxml++ / dtd.cc
1 /* dtd.cc
2  * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
3  * are covered by the GNU Lesser General Public License, which should be
4  * included with libxml++ as the file COPYING.
5  */
6
7 #include <libxml++/dtd.h>
8 #include <libxml++/exceptions/parse_error.h>
9 #include <libxml++/io/istreamparserinputbuffer.h>
10
11 #include <libxml/tree.h>
12
13 namespace xmlpp
14 {
15   
16 struct Dtd::Impl
17 {
18   Impl() : dtd(nullptr), is_dtd_owner(false) {}
19
20   _xmlDtd* dtd;
21   bool is_dtd_owner;
22 };
23
24 Dtd::Dtd()
25 : pimpl_(new Impl)
26 {
27 }
28
29 Dtd::Dtd(_xmlDtd* dtd, bool take_ownership)
30 : pimpl_(new Impl)
31 {
32   pimpl_->dtd = dtd;
33   if (dtd)
34   {
35     pimpl_->dtd->_private = this;
36     pimpl_->is_dtd_owner = take_ownership;
37   }
38 }
39
40 Dtd::Dtd(const std::string& filename)
41 : pimpl_(new Impl)
42 {
43   parse_subset("", filename);
44 }
45
46 Dtd::Dtd(const Glib::ustring& external, const Glib::ustring& system)
47 : pimpl_(new Impl)
48 {
49   parse_subset(external, system);
50 }
51
52 Dtd::~Dtd()
53 {
54   release_underlying();
55 }
56
57 void Dtd::parse_file(const std::string& filename)
58 {
59   parse_subset("", filename);
60 }
61
62 void Dtd::parse_subset(const Glib::ustring& external, const Glib::ustring& system)
63 {
64   release_underlying(); // Free any existing dtd.
65   xmlResetLastError();
66
67   auto dtd = xmlParseDTD(
68     external.empty() ? nullptr : (const xmlChar*)external.c_str(),
69     system.empty() ? nullptr : (const xmlChar*)system.c_str());
70
71   if (!dtd)
72   {
73     throw parse_error("Dtd could not be parsed.\n" + format_xml_error());
74   }
75
76   pimpl_->dtd = dtd;
77   pimpl_->dtd->_private = this;
78   pimpl_->is_dtd_owner = true;
79 }
80
81 void Dtd::parse_memory(const Glib::ustring& contents)
82 {
83   // Prepare an istream with buffer
84   std::istringstream is(contents);
85
86   parse_stream(is);
87 }
88
89 void Dtd::parse_stream(std::istream& in)
90 {
91   release_underlying(); // Free any existing dtd.
92   xmlResetLastError();
93
94   IStreamParserInputBuffer ibuff(in);
95
96   auto dtd = xmlIOParseDTD(nullptr, ibuff.cobj(), XML_CHAR_ENCODING_UTF8);
97
98   if (!dtd)
99   {
100     throw parse_error("Dtd could not be parsed.\n" + format_xml_error());
101   }
102
103   pimpl_->dtd = dtd;
104   pimpl_->dtd->_private = this;
105   pimpl_->is_dtd_owner = true;
106 }
107
108 Glib::ustring Dtd::get_name() const
109 {
110   return (pimpl_->dtd && pimpl_->dtd->name) ? (const char*)pimpl_->dtd->name : "";
111 }
112
113 Glib::ustring Dtd::get_external_id() const
114 {
115   return (pimpl_->dtd && pimpl_->dtd->ExternalID) ? (const char*)pimpl_->dtd->ExternalID : "";
116 }
117
118 Glib::ustring Dtd::get_system_id() const
119 {
120   return (pimpl_->dtd && pimpl_->dtd->SystemID) ? (const char*)pimpl_->dtd->SystemID : "";
121 }
122
123 _xmlDtd* Dtd::cobj()
124 {
125   return pimpl_->dtd;
126 }
127
128 const _xmlDtd* Dtd::cobj() const
129 {
130   return pimpl_->dtd;
131 }
132
133 void Dtd::release_underlying()
134 {
135   if (pimpl_->dtd)
136   {
137     pimpl_->dtd->_private = nullptr;
138     if (pimpl_->is_dtd_owner)
139     {
140       xmlFreeDtd(pimpl_->dtd);
141       pimpl_->is_dtd_owner = false;
142     }
143     pimpl_->dtd = nullptr;
144   }
145 }
146
147 } //namespace xmlpp