Rename a few bits.
[libcxml.git] / src / cxml.h
1 #ifndef LIBCXML_CXML_H
2 #define LIBCXML_CXML_H
3
4 #include <string>
5 #include <list>
6 #include <stdint.h>
7 #include <boost/shared_ptr.hpp>
8 #include <boost/optional.hpp>
9 #include <boost/lexical_cast.hpp>
10 #include <boost/algorithm/string/erase.hpp>
11 #include <glibmm.h>
12
13 namespace xmlpp {
14         class Node;
15         class DomParser;
16 }
17
18 namespace cxml {
19
20 /** @brief An error */
21 class Error : public std::exception
22 {
23 public:
24         /** Construct an Error exception.
25          *  @param message Error message.
26          */
27         Error (std::string const & message) : _message (message) {}
28
29         /** Error destructor */
30         ~Error () throw () {}
31
32         /** @return error message.  Caller must not free the returned
33          *  value.
34          */
35         char const * what () const throw () {
36                 return _message.c_str ();
37         }
38
39 private:
40         /** error message */
41         std::string _message;
42 };
43
44 /** @brief A wrapper for a xmlpp::Node which simplifies parsing */
45 class Node
46 {
47 public:
48         Node ();
49         
50         /** Construct a Node from an xmlpp::Node.  This class will
51          *  not destroy the xmlpp::Node.
52          *  @param node xmlpp::Node.
53          */
54         Node (xmlpp::Node const * node);
55
56         std::string name () const;
57
58         /* A set of methods which look up a child of this node by
59          * its name, and return its contents as some type or other.
60          *
61          * If, for example, this object has been created with
62          * a node named "Fred", we might have the following XML:
63          *
64          * <Fred>
65          *   <Jim>42</Jim>
66          * </Fred>
67          *
68          * string_child ("Jim") would return "42"
69          * number_child<int64_t> ("Jim") would return 42.
70          * ...and so on.
71          *
72          * The methods not marked "optional" will throw an exception
73          * if the child node is not present.  The "optional" methods
74          * will return an empty boost::optional<> in that case.
75          *
76          * All methods will also throw an exception if there is more
77          * than one of the specified child node.
78          */
79
80         std::string string_child (std::string c) const;
81         boost::optional<std::string> optional_string_child (std::string) const;
82
83         bool bool_child (std::string) const;
84         boost::optional<bool> optional_bool_child (std::string) const;
85
86         template <class T>
87         T number_child (std::string c) const
88         {
89                 std::string s = string_child (c);
90                 boost::erase_all (s, " ");
91                 return boost::lexical_cast<T> (s);
92         }
93
94         template <class T>
95         boost::optional<T> optional_number_child (std::string c) const
96         {
97                 boost::optional<std::string> s = optional_string_child (c);
98                 if (!s) {
99                         return boost::optional<T> ();
100                 }
101
102                 std::string t = s.get ();
103                 boost::erase_all (t, " ");
104                 return boost::optional<T> (boost::lexical_cast<T> (t));
105         }
106                 
107         /** This will mark a child as to be ignored when calling done() */
108         void ignore_child (std::string) const;
109
110         /** Check whether all children of this Node have been looked up
111          *  or passed to ignore_child().  If not, an exception is thrown.
112          */
113         void done () const;
114
115         /* These methods look for an attribute of this node, in the
116          * same way as the child methods do.
117          */
118
119         std::string string_attribute (std::string) const;
120         boost::optional<std::string> optional_string_attribute (std::string) const;
121
122         bool bool_attribute (std::string) const;
123         boost::optional<bool> optional_bool_attribute (std::string) const;
124
125         template <class T>
126         T number_attribute (std::string c) const
127         {
128                 std::string s = string_attribute (c);
129                 boost::erase_all (s, " ");
130                 return boost::lexical_cast<T> (s);
131         }
132
133         template <class T>
134         boost::optional<T> optional_number_attribute (std::string c) const
135         {
136                 boost::optional<std::string> s = optional_string_attribute (c);
137                 if (!s) {
138                         return boost::optional<T> ();
139                 }
140
141                 std::string t = s.get ();
142                 boost::erase_all (t, " ");
143                 return boost::optional<T> (boost::lexical_cast<T> (t));
144         }
145
146         /** @return The content of this node */
147         std::string content () const;
148
149         boost::shared_ptr<Node> node_child (std::string) const;
150         boost::shared_ptr<Node> optional_node_child (std::string) const;
151
152         std::list<boost::shared_ptr<Node> > node_children (std::string) const;
153         
154 protected:
155         xmlpp::Node const * _node;
156         
157 private:
158         mutable std::list<Glib::ustring> _taken;
159 };
160
161 class File : public Node
162 {
163 public:
164         File (std::string file, std::string root_name);
165         virtual ~File ();
166
167 private:
168         xmlpp::DomParser* _parser;
169 };
170
171 }
172
173 #endif