]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_RGW_XML_H | |
5 | #define CEPH_RGW_XML_H | |
6 | ||
7 | #include <map> | |
8 | #include <string> | |
9 | #include <iosfwd> | |
10 | #include <include/types.h> | |
11 | #include <common/Formatter.h> | |
12 | ||
13 | using namespace std; | |
14 | ||
15 | ||
16 | class XMLObj; | |
17 | ||
18 | class XMLObjIter { | |
19 | typedef map<string, XMLObj *>::iterator map_iter_t; | |
20 | map_iter_t cur; | |
21 | map_iter_t end; | |
22 | public: | |
23 | XMLObjIter(); | |
24 | ~XMLObjIter(); | |
25 | void set(const XMLObjIter::map_iter_t &_cur, const XMLObjIter::map_iter_t &_end); | |
26 | XMLObj *get_next(); | |
27 | }; | |
28 | ||
29 | /** | |
30 | * Represents a block of XML. | |
31 | * Give the class an XML blob, and it will parse the blob into | |
32 | * an attr_name->value map. | |
33 | * This really ought to be an abstract class or something; it | |
34 | * shouldn't be the startpoint for any parsing. Look at RGWXMLParser for that. | |
35 | */ | |
36 | class XMLObj | |
37 | { | |
38 | XMLObj *parent; | |
39 | string obj_type; | |
40 | protected: | |
41 | string data; | |
42 | multimap<string, XMLObj *> children; | |
43 | map<string, string> attr_map; | |
44 | public: | |
45 | ||
46 | XMLObj() : parent(NULL) {} | |
47 | ||
48 | virtual ~XMLObj(); | |
49 | bool xml_start(XMLObj *parent, const char *el, const char **attr); | |
50 | virtual bool xml_end(const char *el); | |
51 | virtual void xml_handle_data(const char *s, int len); | |
52 | string& get_data(); | |
53 | XMLObj *get_parent(); | |
54 | void add_child(string el, XMLObj *obj); | |
55 | bool get_attr(string name, string& attr); | |
56 | XMLObjIter find(string name); | |
57 | XMLObj *find_first(string name); | |
58 | ||
59 | friend ostream& operator<<(ostream &out, const XMLObj &obj); | |
60 | }; | |
61 | ||
62 | struct XML_ParserStruct; | |
63 | class RGWXMLParser : public XMLObj | |
64 | { | |
65 | XML_ParserStruct *p; | |
66 | char *buf; | |
67 | int buf_len; | |
68 | XMLObj *cur_obj; | |
69 | vector<XMLObj *> objs; | |
70 | list<XMLObj *> allocated_objs; | |
71 | list<XMLObj> unallocated_objs; | |
72 | protected: | |
73 | virtual XMLObj *alloc_obj(const char *el) { | |
74 | return NULL; | |
75 | } | |
76 | public: | |
77 | RGWXMLParser(); | |
78 | ~RGWXMLParser() override; | |
79 | bool init(); | |
80 | bool xml_start(const char *el, const char **attr); | |
81 | bool xml_end(const char *el) override; | |
82 | void handle_data(const char *s, int len); | |
83 | ||
84 | bool parse(const char *buf, int len, int done); | |
85 | const char *get_xml() { return buf; } | |
86 | void set_failure() { success = false; } | |
87 | ||
88 | private: | |
89 | bool success; | |
90 | }; | |
91 | ||
92 | class RGWXMLDecoder { | |
93 | public: | |
94 | struct err { | |
95 | string message; | |
96 | ||
97 | explicit err(const string& m) : message(m) {} | |
98 | }; | |
99 | ||
100 | class XMLParser : public RGWXMLParser { | |
101 | public: | |
102 | XMLParser() {} | |
103 | ~XMLParser() override {} | |
104 | } parser; | |
105 | ||
106 | explicit RGWXMLDecoder(bufferlist& bl) { | |
107 | if (!parser.parse(bl.c_str(), bl.length(), 1)) { | |
108 | cout << "RGWXMLDecoder::err()" << std::endl; | |
109 | throw RGWXMLDecoder::err("failed to parse XML input"); | |
110 | } | |
111 | } | |
112 | ||
113 | template<class T> | |
114 | static bool decode_xml(const char *name, T& val, XMLObj *obj, bool mandatory = false); | |
115 | ||
116 | template<class C> | |
117 | static bool decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *obj), XMLObj *obj, bool mandatory = false); | |
118 | ||
119 | template<class T> | |
120 | static void decode_xml(const char *name, T& val, T& default_val, XMLObj *obj); | |
121 | }; | |
122 | ||
123 | template<class T> | |
124 | void decode_xml_obj(T& val, XMLObj *obj) | |
125 | { | |
126 | val.decode_xml(obj); | |
127 | } | |
128 | ||
129 | static inline void decode_xml_obj(string& val, XMLObj *obj) | |
130 | { | |
131 | val = obj->get_data(); | |
132 | } | |
133 | ||
134 | void decode_xml_obj(unsigned long long& val, XMLObj *obj); | |
135 | void decode_xml_obj(long long& val, XMLObj *obj); | |
136 | void decode_xml_obj(unsigned long& val, XMLObj *obj); | |
137 | void decode_xml_obj(long& val, XMLObj *obj); | |
138 | void decode_xml_obj(unsigned& val, XMLObj *obj); | |
139 | void decode_xml_obj(int& val, XMLObj *obj); | |
140 | void decode_xml_obj(bool& val, XMLObj *obj); | |
141 | void decode_xml_obj(bufferlist& val, XMLObj *obj); | |
142 | class utime_t; | |
143 | void decode_xml_obj(utime_t& val, XMLObj *obj); | |
144 | ||
145 | template<class T> | |
146 | void do_decode_xml_obj(list<T>& l, const string& name, XMLObj *obj) | |
147 | { | |
148 | l.clear(); | |
149 | ||
150 | XMLObjIter iter = obj->find(name); | |
151 | XMLObj *o; | |
152 | ||
153 | while ((o = iter.get_next())) { | |
154 | T val; | |
155 | decode_xml_obj(val, o); | |
156 | l.push_back(val); | |
157 | } | |
158 | } | |
159 | ||
160 | template<class T> | |
161 | void do_decode_xml_obj(vector<T>& l, const string& name, XMLObj *obj) | |
162 | { | |
163 | l.clear(); | |
164 | ||
165 | XMLObjIter iter = obj->find(name); | |
166 | XMLObj *o; | |
167 | ||
168 | while (o = iter.get_next()) { | |
169 | T val; | |
170 | decode_xml_obj(val, o); | |
171 | l.push_back(val); | |
172 | } | |
173 | } | |
174 | ||
175 | template<class T> | |
176 | bool RGWXMLDecoder::decode_xml(const char *name, T& val, XMLObj *obj, bool mandatory) | |
177 | { | |
178 | XMLObjIter iter = obj->find(name); | |
179 | XMLObj *o = iter.get_next(); | |
180 | if (!o) { | |
181 | if (mandatory) { | |
182 | string s = "missing mandatory field " + string(name); | |
183 | throw err(s); | |
184 | } | |
185 | val = T(); | |
186 | return false; | |
187 | } | |
188 | ||
189 | try { | |
190 | decode_xml_obj(val, o); | |
191 | } catch (err& e) { | |
192 | string s = string(name) + ": "; | |
193 | s.append(e.message); | |
194 | throw err(s); | |
195 | } | |
196 | ||
197 | return true; | |
198 | } | |
199 | ||
200 | template<class C> | |
201 | bool RGWXMLDecoder::decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *), XMLObj *obj, bool mandatory) | |
202 | { | |
203 | container.clear(); | |
204 | ||
205 | XMLObjIter iter = obj->find(name); | |
206 | XMLObj *o = iter.get_next(); | |
207 | if (!o) { | |
208 | if (mandatory) { | |
209 | string s = "missing mandatory field " + string(name); | |
210 | throw err(s); | |
211 | } | |
212 | return false; | |
213 | } | |
214 | ||
215 | try { | |
216 | decode_xml_obj(container, cb, o); | |
217 | } catch (err& e) { | |
218 | string s = string(name) + ": "; | |
219 | s.append(e.message); | |
220 | throw err(s); | |
221 | } | |
222 | ||
223 | return true; | |
224 | } | |
225 | ||
226 | template<class T> | |
227 | void RGWXMLDecoder::decode_xml(const char *name, T& val, T& default_val, XMLObj *obj) | |
228 | { | |
229 | XMLObjIter iter = obj->find(name); | |
230 | XMLObj *o = iter.get_next(); | |
231 | if (!o) { | |
232 | val = default_val; | |
233 | return; | |
234 | } | |
235 | ||
236 | try { | |
237 | decode_xml_obj(val, o); | |
238 | } catch (err& e) { | |
239 | val = default_val; | |
240 | string s = string(name) + ": "; | |
241 | s.append(e.message); | |
242 | throw err(s); | |
243 | } | |
244 | } | |
245 | ||
246 | template<class T> | |
247 | static void encode_xml(const char *name, const T& val, ceph::Formatter *f) | |
248 | { | |
249 | f->open_object_section(name); | |
250 | val.dump_xml(f); | |
251 | f->close_section(); | |
252 | } | |
253 | ||
254 | void encode_xml(const char *name, const string& val, ceph::Formatter *f); | |
255 | void encode_xml(const char *name, const char *val, ceph::Formatter *f); | |
256 | void encode_xml(const char *name, bool val, ceph::Formatter *f); | |
257 | void encode_xml(const char *name, int val, ceph::Formatter *f); | |
258 | void encode_xml(const char *name, unsigned val, ceph::Formatter *f); | |
259 | void encode_xml(const char *name, long val, ceph::Formatter *f); | |
260 | void encode_xml(const char *name, unsigned long val, ceph::Formatter *f); | |
261 | void encode_xml(const char *name, long long val, ceph::Formatter *f); | |
262 | void encode_xml(const char *name, const utime_t& val, ceph::Formatter *f); | |
263 | void encode_xml(const char *name, const bufferlist& bl, ceph::Formatter *f); | |
264 | void encode_xml(const char *name, long long val, ceph::Formatter *f); | |
265 | void encode_xml(const char *name, long long unsigned val, ceph::Formatter *f); | |
266 | ||
267 | template<class T> | |
268 | static void do_encode_xml(const char *name, const std::list<T>& l, const char *entry_name, ceph::Formatter *f) | |
269 | { | |
270 | f->open_array_section(name); | |
271 | for (typename std::list<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) { | |
272 | encode_xml(entry_name, *iter, f); | |
273 | } | |
274 | f->close_section(); | |
275 | } | |
276 | ||
277 | ||
278 | ||
279 | #endif |