/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
- This program is free software; you can redistribute it and/or modify
+ This file is part of libcxml.
+
+ libcxml is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ libcxml 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 General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with libcxml. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBCXML_CXML_H
#define LIBCXML_CXML_H
-#include <string>
-#include <list>
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/erase.hpp>
-#include <glibmm.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+/* Hack for OS X compile failure; see https://bugs.launchpad.net/hugin/+bug/910160 */
+#ifdef check
+#undef check
+#endif
namespace xmlpp {
class Node;
std::string _message;
};
+/** A sort-of version of boost::lexical_cast that does uses the "C"
+ * locale (i.e. no thousands separators and a . for the decimal separator).
+ */
+template <typename P, typename Q>
+P
+raw_convert (Q)
+{
+ /* We can't write a generic version of raw_convert; all required
+ versions must be specialised.
+ */
+ BOOST_STATIC_ASSERT (sizeof(Q) == 0);
+}
+
+template <>
+int
+raw_convert (std::string v);
+
+template <>
+unsigned int
+raw_convert (std::string v);
+
+template <>
+long int
+raw_convert (std::string v);
+
+template <>
+long unsigned int
+raw_convert (std::string v);
+
+template <>
+long long
+raw_convert (std::string v);
+
+template <>
+long long unsigned
+raw_convert (std::string v);
+
+template <>
+float
+raw_convert (std::string v);
+
+template <>
+double
+raw_convert (std::string v);
+
/** @brief A wrapper for a xmlpp::Node which simplifies parsing */
class Node
{
public:
Node ();
-
+
/** Construct a Node from an xmlpp::Node. This class will
* not destroy the xmlpp::Node.
* @param node xmlpp::Node.
template <class T>
T number_child (std::string c) const
{
- std::string s = string_child (c);
+ auto s = string_child (c);
boost::erase_all (s, " ");
- std::stringstream t;
- t.imbue (std::locale::classic ());
- t << s;
- T n;
- t >> n;
- return n;
+ return raw_convert<T> (s);
}
template <class T>
boost::optional<T> optional_number_child (std::string c) const
{
- boost::optional<std::string> s = optional_string_child (c);
+ auto s = optional_string_child (c);
if (!s) {
- return boost::optional<T> ();
+ return {};
}
- std::string t = s.get ();
+ auto t = s.get ();
boost::erase_all (t, " ");
- std::stringstream u;
- u.imbue (std::locale::classic ());
- u << t;
- T n;
- u >> n;
- return n;
+ return raw_convert<T> (t);
}
-
+
/** This will mark a child as to be ignored when calling done() */
void ignore_child (std::string) const;
{
std::string s = string_attribute (c);
boost::erase_all (s, " ");
- std::stringstream t;
- t.imbue (std::locale::classic ());
- t << s;
- T n;
- t >> n;
- return n;
+ return raw_convert<T> (s);
}
template <class T>
boost::optional<T> optional_number_attribute (std::string c) const
{
- boost::optional<std::string> s = optional_string_attribute (c);
+ auto s = optional_string_attribute (c);
if (!s) {
return boost::optional<T> ();
}
- std::string t = s.get ();
+ auto t = s.get ();
boost::erase_all (t, " ");
- std::stringstream u;
- u.imbue (std::locale::classic ());
- u << t;
- T n;
- t >> n;
- return n;
+ return raw_convert<T> (t);
}
- /** @return The content of this node */
+ /** @return The text content of this node (excluding comments or CDATA) */
std::string content () const;
/** @return namespace URI of this node */
/** @return namespace prefix of this node */
std::string namespace_prefix () const;
- boost::shared_ptr<Node> node_child (std::string) const;
- boost::shared_ptr<Node> optional_node_child (std::string) const;
+ std::shared_ptr<Node> node_child (std::string) const;
+ std::shared_ptr<Node> optional_node_child (std::string) const;
- std::list<boost::shared_ptr<Node> > node_children (std::string) const;
+ std::vector<std::shared_ptr<Node>> node_children () const;
+ std::vector<std::shared_ptr<Node>> node_children (std::string) const;
xmlpp::Node* node () const {
return _node;
}
-
+
protected:
xmlpp::Node* _node;
-
+
private:
- mutable std::list<Glib::ustring> _taken;
+ mutable std::vector<std::string> _taken;
};
-typedef boost::shared_ptr<cxml::Node> NodePtr;
+typedef std::shared_ptr<cxml::Node> NodePtr;
+typedef std::shared_ptr<const cxml::Node> ConstNodePtr;
class Document : public Node
{
public:
+ Document ();
Document (std::string root_name);
Document (std::string root_name, boost::filesystem::path);
- void read_file (boost::filesystem::path);
- void read_stream (std::istream &);
-
virtual ~Document ();
+ void read_file (boost::filesystem::path);
+ void read_string (std::string);
+
+ std::string root_name () const {
+ return _root_name;
+ }
+
private:
void take_root_node ();
-
+
xmlpp::DomParser* _parser;
std::string _root_name;
};