xmpp_stanza.hpp 3.56 KB
Newer Older
1 2 3 4 5 6 7
#ifndef XMPP_STANZA_INCLUDED
# define XMPP_STANZA_INCLUDED

#include <unordered_map>
#include <string>
#include <vector>

louiz’'s avatar
louiz’ committed
8
std::string xml_escape(const std::string& data);
9
std::string xml_unescape(const std::string& data);
louiz’'s avatar
louiz’ committed
10

11 12 13 14 15 16 17 18 19 20 21 22 23
/**
 * Raised on operator[] when the attribute does not exist
 */
class AttributeNotFound: public std::exception
{
};

/**
 * Represent an XML node. It has
 * - A parent XML node (in the case of the first-level nodes, the parent is
     nullptr)
 * - zero, one or more children XML nodes
 * - A name
24 25 26
 * - A map of attributes
 * - inner data (text inside the node)
 * - tail data (text just after the node)
27 28 29 30 31 32 33 34
 */
class XmlNode
{
public:
  explicit XmlNode(const std::string& name, XmlNode* parent);
  explicit XmlNode(const std::string& name);
  XmlNode(XmlNode&& node):
    name(std::move(node.name)),
35 36
    parent(node.parent),
    closed(node.closed),
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
    attributes(std::move(node.attributes)),
    children(std::move(node.children)),
    inner(std::move(node.inner)),
    tail(std::move(node.tail))
  {
    node.parent = nullptr;
  }

  ~XmlNode();

  void delete_all_children();
  void set_attribute(const std::string& name, const std::string& value);
  /**
   * Set the content of the tail, that is the text just after this node
   */
  void set_tail(const std::string& data);
  /**
54 55 56 57 58 59 60
   * Append the given data to the content of the tail. This exists because
   * the expat library may provide the complete text of an element in more
   * than one call
   */
  void add_to_tail(const std::string& data);
  /**
   * Set the content of the inner, that is the text inside this node.
61 62
   */
  void set_inner(const std::string& data);
63 64 65 66 67
  /**
   * Append the given data to the content of the inner. For the reason
   * described in add_to_tail comment.
   */
  void add_to_inner(const std::string& data);
louiz’'s avatar
louiz’ committed
68 69 70 71
  /**
   * Get the content of inner
   */
  std::string get_inner() const;
72 73 74 75
  /**
   * Get the content of the tail
   */
  std::string get_tail() const;
louiz’'s avatar
louiz’ committed
76 77 78 79
  /**
   * Get a pointer to the first child element with that name
   */
  XmlNode* get_child(const std::string& name) const;
80 81 82 83 84 85 86 87 88
  /**
   * Add a node child to this node. Assign this node to the child’s parent.
   * Returns a pointer to the newly added child.
   */
  XmlNode* add_child(XmlNode* child);
  XmlNode* add_child(XmlNode&& child);
  /**
   * Returns the last of the children
   */
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
  XmlNode* get_last_child() const;
  /**
   * Mark this node as closed, nothing else
   */
  void close();
  XmlNode* get_parent() const;
  const std::string& get_name() const;
  /**
   * Serialize the stanza into a string
   */
  std::string to_string() const;
  /**
   * Whether or not this node has at least one child (if not, this is a leaf
   * node)
   */
  bool has_children() const;
  /**
   * Gets the value for the given attribute, raises AttributeNotFound if the
   * node as no such attribute.
   */
  const std::string& operator[](const std::string& name) const;
  /**
   * Use this to set an attribute's value, like node["id"] = "12";
   */
  std::string& operator[](const std::string& name);

private:
  std::string name;
  XmlNode* parent;
  bool closed;
  std::unordered_map<std::string, std::string> attributes;
  std::vector<XmlNode*> children;
  std::string inner;
  std::string tail;

  XmlNode(const XmlNode&) = delete;
  XmlNode& operator=(const XmlNode&) = delete;
  XmlNode& operator=(XmlNode&&) = delete;
};

/**
 * An XMPP stanza is just an XML node of level 2 in the XMPP document (the
 * level 1 ones are the <stream::stream/>, and the ones about 2 are just the
 * content of the stanzas)
 */
typedef XmlNode Stanza;

#endif // XMPP_STANZA_INCLUDED