--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_RGW_XML_H
+#define CEPH_RGW_XML_H
+
+#include <map>
+#include <string>
+#include <iosfwd>
+#include <include/types.h>
+#include <common/Formatter.h>
+
+class XMLObj;
+
+class XMLObjIter {
+ typedef map<string, XMLObj *>::iterator map_iter_t;
+ map_iter_t cur;
+ map_iter_t end;
+public:
+ XMLObjIter();
+ ~XMLObjIter();
+ void set(const XMLObjIter::map_iter_t &_cur, const XMLObjIter::map_iter_t &_end);
+ XMLObj *get_next();
+};
+
+/**
+ * Represents a block of XML.
+ * Give the class an XML blob, and it will parse the blob into
+ * an attr_name->value map.
+ * This really ought to be an abstract class or something; it
+ * shouldn't be the startpoint for any parsing. Look at RGWXMLParser for that.
+ */
+class XMLObj
+{
+ XMLObj *parent;
+ string obj_type;
+protected:
+ string data;
+ multimap<string, XMLObj *> children;
+ map<string, string> attr_map;
+public:
+
+ XMLObj() : parent(NULL) {}
+
+ virtual ~XMLObj();
+ bool xml_start(XMLObj *parent, const char *el, const char **attr);
+ virtual bool xml_end(const char *el);
+ virtual void xml_handle_data(const char *s, int len);
+ string& get_data();
+ XMLObj *get_parent();
+ void add_child(string el, XMLObj *obj);
+ bool get_attr(string name, string& attr);
+ XMLObjIter find(string name);
+ XMLObj *find_first(string name);
+
+ friend ostream& operator<<(ostream &out, const XMLObj &obj);
+};
+
+struct XML_ParserStruct;
+class RGWXMLParser : public XMLObj
+{
+ XML_ParserStruct *p;
+ char *buf;
+ int buf_len;
+ XMLObj *cur_obj;
+ vector<XMLObj *> objs;
+ list<XMLObj *> allocated_objs;
+ list<XMLObj> unallocated_objs;
+protected:
+ virtual XMLObj *alloc_obj(const char *el) {
+ return NULL;
+ }
+public:
+ RGWXMLParser();
+ ~RGWXMLParser() override;
+ bool init();
+ bool xml_start(const char *el, const char **attr);
+ bool xml_end(const char *el) override;
+ void handle_data(const char *s, int len);
+
+ bool parse(const char *buf, int len, int done);
+ const char *get_xml() { return buf; }
+ void set_failure() { success = false; }
+
+private:
+ bool success;
+};
+
+class RGWXMLDecoder {
+public:
+ struct err {
+ string message;
+
+ explicit err(const string& m) : message(m) {}
+ };
+
+ class XMLParser : public RGWXMLParser {
+ public:
+ XMLParser() {}
+ ~XMLParser() override {}
+ } parser;
+
+ explicit RGWXMLDecoder(bufferlist& bl) {
+ if (!parser.parse(bl.c_str(), bl.length(), 1)) {
+ cout << "RGWXMLDecoder::err()" << std::endl;
+ throw RGWXMLDecoder::err("failed to parse XML input");
+ }
+ }
+
+ template<class T>
+ static bool decode_xml(const char *name, T& val, XMLObj *obj, bool mandatory = false);
+
+ template<class C>
+ static bool decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *obj), XMLObj *obj, bool mandatory = false);
+
+ template<class T>
+ static void decode_xml(const char *name, T& val, T& default_val, XMLObj *obj);
+};
+
+template<class T>
+void decode_xml_obj(T& val, XMLObj *obj)
+{
+ val.decode_xml(obj);
+}
+
+static inline void decode_xml_obj(string& val, XMLObj *obj)
+{
+ val = obj->get_data();
+}
+
+void decode_xml_obj(unsigned long long& val, XMLObj *obj);
+void decode_xml_obj(long long& val, XMLObj *obj);
+void decode_xml_obj(unsigned long& val, XMLObj *obj);
+void decode_xml_obj(long& val, XMLObj *obj);
+void decode_xml_obj(unsigned& val, XMLObj *obj);
+void decode_xml_obj(int& val, XMLObj *obj);
+void decode_xml_obj(bool& val, XMLObj *obj);
+void decode_xml_obj(bufferlist& val, XMLObj *obj);
+class utime_t;
+void decode_xml_obj(utime_t& val, XMLObj *obj);
+
+template<class T>
+void do_decode_xml_obj(list<T>& l, const string& name, XMLObj *obj)
+{
+ l.clear();
+
+ XMLObjIter iter = obj->find(name);
+ XMLObj *o;
+
+ while ((o = iter.get_next())) {
+ T val;
+ decode_xml_obj(val, o);
+ l.push_back(val);
+ }
+}
+
+template<class T>
+void do_decode_xml_obj(vector<T>& l, const string& name, XMLObj *obj)
+{
+ l.clear();
+
+ XMLObjIter iter = obj->find(name);
+ XMLObj *o;
+
+ while (o = iter.get_next()) {
+ T val;
+ decode_xml_obj(val, o);
+ l.push_back(val);
+ }
+}
+
+template<class T>
+bool RGWXMLDecoder::decode_xml(const char *name, T& val, XMLObj *obj, bool mandatory)
+{
+ XMLObjIter iter = obj->find(name);
+ XMLObj *o = iter.get_next();
+ if (!o) {
+ if (mandatory) {
+ string s = "missing mandatory field " + string(name);
+ throw err(s);
+ }
+ val = T();
+ return false;
+ }
+
+ try {
+ decode_xml_obj(val, o);
+ } catch (err& e) {
+ string s = string(name) + ": ";
+ s.append(e.message);
+ throw err(s);
+ }
+
+ return true;
+}
+
+template<class C>
+bool RGWXMLDecoder::decode_xml(const char *name, C& container, void (*cb)(C&, XMLObj *), XMLObj *obj, bool mandatory)
+{
+ container.clear();
+
+ XMLObjIter iter = obj->find(name);
+ XMLObj *o = iter.get_next();
+ if (!o) {
+ if (mandatory) {
+ string s = "missing mandatory field " + string(name);
+ throw err(s);
+ }
+ return false;
+ }
+
+ try {
+ decode_xml_obj(container, cb, o);
+ } catch (err& e) {
+ string s = string(name) + ": ";
+ s.append(e.message);
+ throw err(s);
+ }
+
+ return true;
+}
+
+template<class T>
+void RGWXMLDecoder::decode_xml(const char *name, T& val, T& default_val, XMLObj *obj)
+{
+ XMLObjIter iter = obj->find(name);
+ XMLObj *o = iter.get_next();
+ if (!o) {
+ val = default_val;
+ return;
+ }
+
+ try {
+ decode_xml_obj(val, o);
+ } catch (err& e) {
+ val = default_val;
+ string s = string(name) + ": ";
+ s.append(e.message);
+ throw err(s);
+ }
+}
+
+template<class T>
+static void encode_xml(const char *name, const T& val, ceph::Formatter *f)
+{
+ f->open_object_section(name);
+ val.dump_xml(f);
+ f->close_section();
+}
+
+void encode_xml(const char *name, const string& val, ceph::Formatter *f);
+void encode_xml(const char *name, const char *val, ceph::Formatter *f);
+void encode_xml(const char *name, bool val, ceph::Formatter *f);
+void encode_xml(const char *name, int val, ceph::Formatter *f);
+void encode_xml(const char *name, unsigned val, ceph::Formatter *f);
+void encode_xml(const char *name, long val, ceph::Formatter *f);
+void encode_xml(const char *name, unsigned long val, ceph::Formatter *f);
+void encode_xml(const char *name, long long val, ceph::Formatter *f);
+void encode_xml(const char *name, const utime_t& val, ceph::Formatter *f);
+void encode_xml(const char *name, const bufferlist& bl, ceph::Formatter *f);
+void encode_xml(const char *name, long long val, ceph::Formatter *f);
+void encode_xml(const char *name, long long unsigned val, ceph::Formatter *f);
+
+template<class T>
+static void do_encode_xml(const char *name, const std::list<T>& l, const char *entry_name, ceph::Formatter *f)
+{
+ f->open_array_section(name);
+ for (typename std::list<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) {
+ encode_xml(entry_name, *iter, f);
+ }
+ f->close_section();
+}
+
+
+
+#endif