1 /*
2  * Copyright (C) 2006-2016 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2006 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2008-2009 David Robillard <d@drobilla.net>
5  * Copyright (C) 2008 Hans Baier <hansfbaier@googlemail.com>
6  * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
7  * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
8  * Copyright (C) 2016 Tim Mayberry <mojofunk@gmail.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 #ifndef __XML_H
26 #define __XML_H
27 
28 /* xml++.h
29  * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
30  * are covered by the GNU Lesser General Public License, which should be
31  * included with libxml++ as the file COPYING.
32  * Modified for Ardour and released under the same terms.
33  */
34 
35 #include <string>
36 #include <vector>
37 #include <cstdio>
38 #include <cstdarg>
39 
40 #include <libxml/parser.h>
41 #include <libxml/tree.h>
42 #include <boost/shared_ptr.hpp>
43 
44 #include <glibmm/ustring.h>
45 
46 #include "pbd/string_convert.h"
47 #include "pbd/libpbd_visibility.h"
48 
49 class XMLTree;
50 class XMLNode;
51 
52 class LIBPBD_API XMLProperty {
53 public:
54 	XMLProperty(const std::string& n, const std::string& v = std::string());
55 	~XMLProperty();
56 
name()57 	const std::string& name() const { return _name; }
value()58 	const std::string& value() const { return _value; }
set_value(const std::string & v)59 	const std::string& set_value(const std::string& v) { return _value = v; }
60 
61 private:
62 	std::string _name;
63 	std::string _value;
64 };
65 
66 typedef std::vector<XMLNode *>                   XMLNodeList;
67 typedef std::vector<boost::shared_ptr<XMLNode> > XMLSharedNodeList;
68 typedef XMLNodeList::iterator                    XMLNodeIterator;
69 typedef XMLNodeList::const_iterator              XMLNodeConstIterator;
70 typedef std::vector<XMLProperty*>                XMLPropertyList;
71 typedef XMLPropertyList::iterator                XMLPropertyIterator;
72 typedef XMLPropertyList::const_iterator          XMLPropertyConstIterator;
73 
74 class LIBPBD_API XMLTree {
75 public:
76 	XMLTree();
77 	XMLTree(const std::string& fn, bool validate = false);
78 	XMLTree(const XMLTree*);
79 	~XMLTree();
80 
root()81 	XMLNode* root() const         { return _root; }
set_root(XMLNode * n)82 	XMLNode* set_root(XMLNode* n) { return _root = n; }
83 
filename()84 	const std::string& filename() const               { return _filename; }
set_filename(const std::string & fn)85 	const std::string& set_filename(const std::string& fn) { return _filename = fn; }
86 
compression()87 	int compression() const { return _compression; }
88 	int set_compression(int);
89 
read()90 	bool read() { return read_internal(false); }
read(const std::string & fn)91 	bool read(const std::string& fn) { set_filename(fn); return read_internal(false); }
read_and_validate()92 	bool read_and_validate() { return read_internal(true); }
read_and_validate(const std::string & fn)93 	bool read_and_validate(const std::string& fn) { set_filename(fn); return read_internal(true); }
94 	bool read_buffer(char const*, bool to_tree_doc = false);
95 
96 	bool write() const;
write(const std::string & fn)97 	bool write(const std::string& fn) { set_filename(fn); return write(); }
98 
99 	void debug (FILE*) const;
100 
101 	const std::string& write_buffer() const;
102 
103 	boost::shared_ptr<XMLSharedNodeList> find(const std::string xpath, XMLNode* = 0) const;
104 
105 private:
106 	bool read_internal(bool validate);
107 
108 	std::string _filename;
109 	XMLNode*    _root;
110 	xmlDocPtr   _doc;
111 	int         _compression;
112 };
113 
114 class LIBPBD_API XMLNode {
115 public:
116 	XMLNode(const std::string& name);
117 	XMLNode(const std::string& name, const std::string& content);
118 	XMLNode(const XMLNode& other);
119 	~XMLNode();
120 
121 	XMLNode& operator= (const XMLNode& other);
122 
123 	bool operator== (const XMLNode& other) const;
124 	bool operator!= (const XMLNode& other) const;
125 
name()126 	const std::string& name() const { return _name; }
127 
is_content()128 	bool          is_content() const { return _is_content; }
content()129 	const std::string& content()    const { return _content; }
130 	const std::string& set_content(const std::string&);
131 	XMLNode*      add_content(const std::string& s = std::string());
132 
133 	const XMLNodeList& children(const std::string& str = std::string()) const;
134 	XMLNode* child(const char*) const;
135 	XMLNode* add_child(const char *);
136 	XMLNode* add_child_copy(const XMLNode&);
137 	void     add_child_nocopy(XMLNode&);
138 
139 	std::string attribute_value();  //throws XMLException if attribute doesn't exist
140 
properties()141 	const XMLPropertyList& properties() const { return _proplist; }
142 	XMLProperty const *    property(const char*) const;
143 	XMLProperty const *    property(const std::string&) const;
144 	XMLProperty *    property(const char*);
145 	XMLProperty *    property(const std::string&);
146 
147 	bool has_property_with_value (const std::string&, const std::string&) const;
148 
149 	bool set_property (const char* name, const std::string& value);
150 
set_property(const char * name,const char * cstr)151 	bool set_property (const char* name, const char* cstr) {
152 		return set_property (name, std::string(cstr));
153 	}
154 
set_property(const char * name,const Glib::ustring & ustr)155 	bool set_property (const char* name, const Glib::ustring& ustr)
156 	{
157 		return set_property (name, ustr.raw ());
158 	}
159 
160 	template<class T>
set_property(const char * name,const T & value)161 	bool set_property (const char* name, const T& value)
162 	{
163 		std::string str;
164 		if (!PBD::to_string<T> (value, str)) {
165 			return false;
166 		}
167 		return set_property(name, str);
168 	}
169 
170 	bool get_property (const char* name, std::string& value) const;
171 
172 	template <class T>
get_property(const char * name,T & value)173 	bool get_property (const char* name, T& value) const
174 	{
175 		XMLProperty const* const prop = property (name);
176 		if (!prop) {
177 			return false;
178 		}
179 
180 		return PBD::string_to<T> (prop->value (), value);
181 	}
182 
183 	void remove_property(const std::string&);
184 	void remove_property_recursively(const std::string&);
185 
186 	/** Remove all nodes with the name passed to remove_nodes */
187 	void remove_nodes (const std::string&);
188 	/** Remove and delete all nodes with the name passed to remove_nodes */
189 	void remove_nodes_and_delete (const std::string&);
190 	/** Remove and delete all nodes with property prop matching val */
191 	void remove_nodes_and_delete (const std::string& propname, const std::string& val);
192 	/** Remove and delete first node with given name and prop matching val */
193 	void remove_node_and_delete (const std::string& n, const std::string& propname, const std::string& val);
194 
195 	void dump (std::ostream &, std::string p = "") const;
196 
197 private:
198 	std::string         _name;
199 	bool                _is_content;
200 	std::string         _content;
201 	XMLNodeList         _children;
202 	XMLPropertyList     _proplist;
203 	mutable XMLNodeList _selected_children;
204 
205 	void clear_lists ();
206 };
207 
208 class LIBPBD_API XMLException: public std::exception {
209 public:
XMLException(const std::string msg)210 	explicit XMLException(const std::string msg) : _message(msg) {}
~XMLException()211 	virtual ~XMLException() throw() {}
212 
what()213 	virtual const char* what() const throw() { return _message.c_str(); }
214 
215 private:
216 	std::string _message;
217 };
218 
219 #endif /* __XML_H */
220 
221