]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_xml.h
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / rgw / rgw_xml.h
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae 3
1e59de90 4#pragma once
7c673cae
FG
5
6#include <map>
9f95a23c 7#include <stdexcept>
7c673cae
FG
8#include <string>
9#include <iosfwd>
10#include <include/types.h>
11#include <common/Formatter.h>
12
7c673cae 13class XMLObj;
11fdf7f2 14class RGWXMLParser;
7c673cae
FG
15
16class XMLObjIter {
7c673cae 17public:
20effc67
TL
18 typedef std::map<std::string, XMLObj *>::iterator map_iter_t;
19 typedef std::map<std::string, XMLObj *>::iterator const_map_iter_t;
11fdf7f2 20
7c673cae 21 XMLObjIter();
1e59de90 22 virtual ~XMLObjIter();
11fdf7f2 23 void set(const XMLObjIter::const_map_iter_t &_cur, const XMLObjIter::const_map_iter_t &_end);
7c673cae 24 XMLObj *get_next();
11fdf7f2
TL
25 bool get_name(std::string& name) const;
26
27private:
28 map_iter_t cur;
29 map_iter_t end;
7c673cae
FG
30};
31
32/**
33 * Represents a block of XML.
34 * Give the class an XML blob, and it will parse the blob into
35 * an attr_name->value map.
11fdf7f2 36 * It shouldn't be the start point for any parsing. Look at RGWXMLParser for that.
7c673cae
FG
37 */
38class XMLObj
39{
11fdf7f2 40private:
7c673cae 41 XMLObj *parent;
11fdf7f2 42 std::string obj_type;
7c673cae 43
11fdf7f2
TL
44protected:
45 std::string data;
46 std::multimap<std::string, XMLObj *> children;
47 std::map<std::string, std::string> attr_map;
7c673cae 48
11fdf7f2 49 // invoked at the beginning of the XML tag, and populate any attributes
7c673cae 50 bool xml_start(XMLObj *parent, const char *el, const char **attr);
11fdf7f2
TL
51 // callback invoked at the end of the XML tag
52 // if objects are created while parsing, this should be overwritten in the drived class
7c673cae 53 virtual bool xml_end(const char *el);
11fdf7f2
TL
54 // callback invoked for storing the data of the XML tag
55 // if data manipulation is needed this could be overwritten in the drived class
7c673cae 56 virtual void xml_handle_data(const char *s, int len);
11fdf7f2 57 // get the parent object
7c673cae 58 XMLObj *get_parent();
11fdf7f2
TL
59 // add a child XML object
60 void add_child(const std::string& el, XMLObj *obj);
61
62public:
63 XMLObj() : parent(nullptr) {}
64 virtual ~XMLObj();
65
66 // get the data (as string)
67 const std::string& get_data() const;
68 // get the type of the object (as string)
69 const std::string& get_obj_type() const;
70 bool get_attr(const std::string& name, std::string& attr) const;
71 // return a list of sub-tags matching the name
72 XMLObjIter find(const std::string& name);
73 // return the first sub-tag
74 XMLObjIter find_first();
75 // return the first sub-tags matching the name
76 XMLObj *find_first(const std::string& name);
7c673cae 77
20effc67 78 friend std::ostream& operator<<(std::ostream &out, const XMLObj &obj);
11fdf7f2 79 friend RGWXMLParser;
7c673cae
FG
80};
81
82struct XML_ParserStruct;
11fdf7f2
TL
83
84// an XML parser is an XML object without a parent (root of the tree)
85// the parser could be used in 2 ways:
86//
87// (1) lazy object creation/intrusive API: usually used within the RGWXMLDecode namespace (as RGWXMLDecode::XMLParser)
88// the parser will parse the input and store info, but will not generate the target object. The object can be allocated outside
89// of the parser (stack or heap), and require to implement the decode_xml() API for the values to be populated.
90// note that the decode_xml() calls may throw exceptions if parsing fails
91//
92// (2) object creation while parsing: a new class needs to be derived from RGWXMLParser and implement alloc_obj()
93// API that should create a set of classes derived from XMLObj implementing xml_end() to create the actual target objects
94//
95// There could be a mix-and-match of the 2 types, control over that is in the alloc_obj() call
96// deciding for which tags objects are allocate during parsing and for which tags object allocation is external
97
7c673cae
FG
98class RGWXMLParser : public XMLObj
99{
11fdf7f2 100private:
7c673cae
FG
101 XML_ParserStruct *p;
102 char *buf;
103 int buf_len;
104 XMLObj *cur_obj;
11fdf7f2
TL
105 std::vector<XMLObj *> objs;
106 std::list<XMLObj *> allocated_objs;
107 std::list<XMLObj> unallocated_objs;
108 bool success;
109 bool init_called;
110
111 // calls xml_start() on each parsed object
112 // passed as static callback to actual parser, passes itself as user_data
113 static void call_xml_start(void* user_data, const char *el, const char **attr);
114 // calls xml_end() on each parsed object
115 // passed as static callback to actual parser, passes itself as user_data
116 static void call_xml_end(void* user_data, const char *el);
117 // calls xml_handle_data() on each parsed object
118 // passed as static callback to actual parser, passes itself as user_data
119 static void call_xml_handle_data(void* user_data, const char *s, int len);
120
7c673cae 121protected:
11fdf7f2
TL
122 // if objects are created while parsing, this should be implemented in the derived class
123 // and be a factory for creating the classes derived from XMLObj
1e59de90 124 // note that not all sub-tags has to be constructed here, any such tag which is not
11fdf7f2
TL
125 // constructed will be lazily created when decode_xml() is invoked on it
126 //
127 // note that in case of different tags sharing the same name at different levels
128 // this method should not be used
7c673cae 129 virtual XMLObj *alloc_obj(const char *el) {
11fdf7f2 130 return nullptr;
7c673cae 131 }
11fdf7f2 132
7c673cae
FG
133public:
134 RGWXMLParser();
1e59de90 135 virtual ~RGWXMLParser() override;
7c673cae 136
11fdf7f2
TL
137 // initialize the parser, must be called before parsing
138 bool init();
139 // parse the XML buffer (can be invoked multiple times for incremental parsing)
140 // receives the buffer to parse, its length, and boolean indication (0,1)
141 // whether this is the final chunk of the buffer
7c673cae 142 bool parse(const char *buf, int len, int done);
11fdf7f2
TL
143 // get the XML blob being parsed
144 const char *get_xml() const { return buf; }
7c673cae
FG
145};
146
11fdf7f2 147namespace RGWXMLDecoder {
9f95a23c
TL
148 struct err : std::runtime_error {
149 using runtime_error::runtime_error;
7c673cae
FG
150 };
151
11fdf7f2 152 typedef RGWXMLParser XMLParser;
7c673cae 153
11fdf7f2
TL
154 template<class T>
155 bool decode_xml(const char *name, T& val, XMLObj* obj, bool mandatory = false);
7c673cae
FG
156
157 template<class T>
11fdf7f2 158 bool decode_xml(const char *name, std::vector<T>& v, XMLObj* obj, bool mandatory = false);
7c673cae
FG
159
160 template<class C>
11fdf7f2 161 bool decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *obj), XMLObj *obj, bool mandatory = false);
7c673cae
FG
162
163 template<class T>
11fdf7f2
TL
164 void decode_xml(const char *name, T& val, T& default_val, XMLObj* obj);
165}
166
20effc67 167static inline std::ostream& operator<<(std::ostream &out, RGWXMLDecoder::err& err)
11fdf7f2 168{
9f95a23c 169 return out << err.what();
11fdf7f2 170}
7c673cae
FG
171
172template<class T>
173void decode_xml_obj(T& val, XMLObj *obj)
174{
175 val.decode_xml(obj);
176}
177
20effc67 178static inline void decode_xml_obj(std::string& val, XMLObj *obj)
7c673cae
FG
179{
180 val = obj->get_data();
181}
182
183void decode_xml_obj(unsigned long long& val, XMLObj *obj);
184void decode_xml_obj(long long& val, XMLObj *obj);
185void decode_xml_obj(unsigned long& val, XMLObj *obj);
186void decode_xml_obj(long& val, XMLObj *obj);
187void decode_xml_obj(unsigned& val, XMLObj *obj);
188void decode_xml_obj(int& val, XMLObj *obj);
189void decode_xml_obj(bool& val, XMLObj *obj);
190void decode_xml_obj(bufferlist& val, XMLObj *obj);
191class utime_t;
192void decode_xml_obj(utime_t& val, XMLObj *obj);
193
9f95a23c
TL
194template<class T>
195void decode_xml_obj(std::optional<T>& val, XMLObj *obj)
196{
197 val.emplace();
198 decode_xml_obj(*val, obj);
199}
200
7c673cae 201template<class T>
20effc67 202void do_decode_xml_obj(std::list<T>& l, const std::string& name, XMLObj *obj)
7c673cae
FG
203{
204 l.clear();
205
206 XMLObjIter iter = obj->find(name);
207 XMLObj *o;
208
209 while ((o = iter.get_next())) {
210 T val;
211 decode_xml_obj(val, o);
212 l.push_back(val);
213 }
214}
215
7c673cae
FG
216template<class T>
217bool RGWXMLDecoder::decode_xml(const char *name, T& val, XMLObj *obj, bool mandatory)
218{
219 XMLObjIter iter = obj->find(name);
220 XMLObj *o = iter.get_next();
221 if (!o) {
222 if (mandatory) {
20effc67 223 std::string s = "missing mandatory field " + std::string(name);
7c673cae
FG
224 throw err(s);
225 }
226 val = T();
227 return false;
228 }
229
230 try {
231 decode_xml_obj(val, o);
9f95a23c 232 } catch (const err& e) {
20effc67 233 std::string s = std::string(name) + ": ";
9f95a23c 234 s.append(e.what());
7c673cae
FG
235 throw err(s);
236 }
237
238 return true;
239}
240
11fdf7f2
TL
241template<class T>
242bool RGWXMLDecoder::decode_xml(const char *name, std::vector<T>& v, XMLObj *obj, bool mandatory)
243{
244 XMLObjIter iter = obj->find(name);
245 XMLObj *o = iter.get_next();
246
247 v.clear();
248
249 if (!o) {
250 if (mandatory) {
20effc67 251 std::string s = "missing mandatory field " + std::string(name);
11fdf7f2
TL
252 throw err(s);
253 }
254 return false;
255 }
256
257 do {
258 T val;
259 try {
260 decode_xml_obj(val, o);
9f95a23c 261 } catch (const err& e) {
20effc67 262 std::string s = std::string(name) + ": ";
9f95a23c 263 s.append(e.what());
11fdf7f2
TL
264 throw err(s);
265 }
266 v.push_back(val);
267 } while ((o = iter.get_next()));
268 return true;
269}
270
7c673cae
FG
271template<class C>
272bool RGWXMLDecoder::decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *), XMLObj *obj, bool mandatory)
273{
274 container.clear();
275
276 XMLObjIter iter = obj->find(name);
277 XMLObj *o = iter.get_next();
278 if (!o) {
279 if (mandatory) {
20effc67 280 std::string s = "missing mandatory field " + std::string(name);
7c673cae
FG
281 throw err(s);
282 }
283 return false;
284 }
285
286 try {
287 decode_xml_obj(container, cb, o);
9f95a23c 288 } catch (const err& e) {
20effc67 289 std::string s = std::string(name) + ": ";
9f95a23c 290 s.append(e.what());
7c673cae
FG
291 throw err(s);
292 }
293
294 return true;
295}
296
297template<class T>
298void RGWXMLDecoder::decode_xml(const char *name, T& val, T& default_val, XMLObj *obj)
299{
300 XMLObjIter iter = obj->find(name);
301 XMLObj *o = iter.get_next();
302 if (!o) {
303 val = default_val;
304 return;
305 }
306
307 try {
308 decode_xml_obj(val, o);
9f95a23c 309 } catch (const err& e) {
7c673cae 310 val = default_val;
20effc67 311 std::string s = std::string(name) + ": ";
9f95a23c 312 s.append(e.what());
7c673cae
FG
313 throw err(s);
314 }
315}
316
317template<class T>
318static void encode_xml(const char *name, const T& val, ceph::Formatter *f)
319{
320 f->open_object_section(name);
321 val.dump_xml(f);
322 f->close_section();
323}
324
11fdf7f2
TL
325template<class T>
326static void encode_xml(const char *name, const char *ns, const T& val, ceph::Formatter *f)
327{
328 f->open_object_section_in_ns(name, ns);
329 val.dump_xml(f);
330 f->close_section();
331}
332
20effc67 333void encode_xml(const char *name, const std::string& val, ceph::Formatter *f);
7c673cae
FG
334void encode_xml(const char *name, const char *val, ceph::Formatter *f);
335void encode_xml(const char *name, bool val, ceph::Formatter *f);
336void encode_xml(const char *name, int val, ceph::Formatter *f);
337void encode_xml(const char *name, unsigned val, ceph::Formatter *f);
338void encode_xml(const char *name, long val, ceph::Formatter *f);
339void encode_xml(const char *name, unsigned long val, ceph::Formatter *f);
340void encode_xml(const char *name, long long val, ceph::Formatter *f);
341void encode_xml(const char *name, const utime_t& val, ceph::Formatter *f);
342void encode_xml(const char *name, const bufferlist& bl, ceph::Formatter *f);
7c673cae
FG
343void encode_xml(const char *name, long long unsigned val, ceph::Formatter *f);
344
345template<class T>
346static void do_encode_xml(const char *name, const std::list<T>& l, const char *entry_name, ceph::Formatter *f)
347{
348 f->open_array_section(name);
349 for (typename std::list<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) {
350 encode_xml(entry_name, *iter, f);
351 }
352 f->close_section();
353}
354
9f95a23c
TL
355template<class T>
356static void encode_xml(const char *name, const std::vector<T>& l, ceph::Formatter *f)
357{
358 for (typename std::vector<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) {
359 encode_xml(name, *iter, f);
360 }
361}
362
363template<class T>
364static void encode_xml(const char *name, const std::optional<T>& o, ceph::Formatter *f)
365{
366 if (!o) {
367 return;
368 }
369
370 encode_xml(name, *o, f);
371}