1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
10 #include <include/types.h>
11 #include <common/Formatter.h>
18 typedef map
<std::string
, XMLObj
*>::iterator map_iter_t
;
19 typedef map
<std::string
, XMLObj
*>::iterator const_map_iter_t
;
23 void set(const XMLObjIter::const_map_iter_t
&_cur
, const XMLObjIter::const_map_iter_t
&_end
);
25 bool get_name(std::string
& name
) const;
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.
36 * It shouldn't be the start point for any parsing. Look at RGWXMLParser for that.
46 std::multimap
<std::string
, XMLObj
*> children
;
47 std::map
<std::string
, std::string
> attr_map
;
49 // invoked at the beginning of the XML tag, and populate any attributes
50 bool xml_start(XMLObj
*parent
, const char *el
, const char **attr
);
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
53 virtual bool xml_end(const char *el
);
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
56 virtual void xml_handle_data(const char *s
, int len
);
57 // get the parent object
59 // add a child XML object
60 void add_child(const std::string
& el
, XMLObj
*obj
);
63 XMLObj() : parent(nullptr) {}
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
);
78 friend ostream
& operator<<(ostream
&out
, const XMLObj
&obj
);
82 struct XML_ParserStruct
;
84 // an XML parser is an XML object without a parent (root of the tree)
85 // the parser could be used in 2 ways:
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
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
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
98 class RGWXMLParser
: public XMLObj
105 std::vector
<XMLObj
*> objs
;
106 std::list
<XMLObj
*> allocated_objs
;
107 std::list
<XMLObj
> unallocated_objs
;
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
);
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
124 // note that not all sub-tags has to be constructed here, any such tag which is not
125 // constructed will be lazily created when decode_xml() is invoked on it
127 // note that in case of different tags sharing the same name at different levels
128 // this method should not be used
129 virtual XMLObj
*alloc_obj(const char *el
) {
135 ~RGWXMLParser() override
;
137 // initialize the parser, must be called before parsing
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
142 bool parse(const char *buf
, int len
, int done
);
143 // get the XML blob being parsed
144 const char *get_xml() const { return buf
; }
147 namespace RGWXMLDecoder
{
151 explicit err(const std::string
& m
) : message(m
) {}
154 typedef RGWXMLParser XMLParser
;
157 bool decode_xml(const char *name
, T
& val
, XMLObj
* obj
, bool mandatory
= false);
160 bool decode_xml(const char *name
, std::vector
<T
>& v
, XMLObj
* obj
, bool mandatory
= false);
163 bool decode_xml(const char *name
, C
& container
, void (*cb
)(C
&, XMLObj
*obj
), XMLObj
*obj
, bool mandatory
= false);
166 void decode_xml(const char *name
, T
& val
, T
& default_val
, XMLObj
* obj
);
169 static inline ostream
& operator<<(ostream
&out
, RGWXMLDecoder::err
& err
)
171 return out
<< err
.message
;
175 void decode_xml_obj(T
& val
, XMLObj
*obj
)
180 static inline void decode_xml_obj(string
& val
, XMLObj
*obj
)
182 val
= obj
->get_data();
185 void decode_xml_obj(unsigned long long& val
, XMLObj
*obj
);
186 void decode_xml_obj(long long& val
, XMLObj
*obj
);
187 void decode_xml_obj(unsigned long& val
, XMLObj
*obj
);
188 void decode_xml_obj(long& val
, XMLObj
*obj
);
189 void decode_xml_obj(unsigned& val
, XMLObj
*obj
);
190 void decode_xml_obj(int& val
, XMLObj
*obj
);
191 void decode_xml_obj(bool& val
, XMLObj
*obj
);
192 void decode_xml_obj(bufferlist
& val
, XMLObj
*obj
);
194 void decode_xml_obj(utime_t
& val
, XMLObj
*obj
);
197 void do_decode_xml_obj(list
<T
>& l
, const string
& name
, XMLObj
*obj
)
201 XMLObjIter iter
= obj
->find(name
);
204 while ((o
= iter
.get_next())) {
206 decode_xml_obj(val
, o
);
212 bool RGWXMLDecoder::decode_xml(const char *name
, T
& val
, XMLObj
*obj
, bool mandatory
)
214 XMLObjIter iter
= obj
->find(name
);
215 XMLObj
*o
= iter
.get_next();
218 string s
= "missing mandatory field " + string(name
);
226 decode_xml_obj(val
, o
);
228 string s
= string(name
) + ": ";
237 bool RGWXMLDecoder::decode_xml(const char *name
, std::vector
<T
>& v
, XMLObj
*obj
, bool mandatory
)
239 XMLObjIter iter
= obj
->find(name
);
240 XMLObj
*o
= iter
.get_next();
246 string s
= "missing mandatory field " + string(name
);
255 decode_xml_obj(val
, o
);
257 string s
= string(name
) + ": ";
262 } while ((o
= iter
.get_next()));
267 bool RGWXMLDecoder::decode_xml(const char *name
, C
& container
, void (*cb
)(C
&, XMLObj
*), XMLObj
*obj
, bool mandatory
)
271 XMLObjIter iter
= obj
->find(name
);
272 XMLObj
*o
= iter
.get_next();
275 string s
= "missing mandatory field " + string(name
);
282 decode_xml_obj(container
, cb
, o
);
284 string s
= string(name
) + ": ";
293 void RGWXMLDecoder::decode_xml(const char *name
, T
& val
, T
& default_val
, XMLObj
*obj
)
295 XMLObjIter iter
= obj
->find(name
);
296 XMLObj
*o
= iter
.get_next();
303 decode_xml_obj(val
, o
);
306 string s
= string(name
) + ": ";
313 static void encode_xml(const char *name
, const T
& val
, ceph::Formatter
*f
)
315 f
->open_object_section(name
);
321 static void encode_xml(const char *name
, const char *ns
, const T
& val
, ceph::Formatter
*f
)
323 f
->open_object_section_in_ns(name
, ns
);
328 void encode_xml(const char *name
, const string
& val
, ceph::Formatter
*f
);
329 void encode_xml(const char *name
, const char *val
, ceph::Formatter
*f
);
330 void encode_xml(const char *name
, bool val
, ceph::Formatter
*f
);
331 void encode_xml(const char *name
, int val
, ceph::Formatter
*f
);
332 void encode_xml(const char *name
, unsigned val
, ceph::Formatter
*f
);
333 void encode_xml(const char *name
, long val
, ceph::Formatter
*f
);
334 void encode_xml(const char *name
, unsigned long val
, ceph::Formatter
*f
);
335 void encode_xml(const char *name
, long long val
, ceph::Formatter
*f
);
336 void encode_xml(const char *name
, const utime_t
& val
, ceph::Formatter
*f
);
337 void encode_xml(const char *name
, const bufferlist
& bl
, ceph::Formatter
*f
);
338 void encode_xml(const char *name
, long long unsigned val
, ceph::Formatter
*f
);
341 static void do_encode_xml(const char *name
, const std::list
<T
>& l
, const char *entry_name
, ceph::Formatter
*f
)
343 f
->open_array_section(name
);
344 for (typename
std::list
<T
>::const_iterator iter
= l
.begin(); iter
!= l
.end(); ++iter
) {
345 encode_xml(entry_name
, *iter
, f
);