summaryrefslogtreecommitdiff
path: root/src/rexmpp_xml.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/rexmpp_xml.h')
-rw-r--r--src/rexmpp_xml.h269
1 files changed, 269 insertions, 0 deletions
diff --git a/src/rexmpp_xml.h b/src/rexmpp_xml.h
new file mode 100644
index 0000000..38142ae
--- /dev/null
+++ b/src/rexmpp_xml.h
@@ -0,0 +1,269 @@
+/**
+ @file rexmpp_xml.h
+ @brief XML structures and functions for rexmpp
+ @author defanor <defanor@uberspace.net>
+ @date 2023
+ @copyright MIT license.
+*/
+
+#ifndef REXMPP_XML_H
+#define REXMPP_XML_H
+
+#include <stdio.h>
+
+typedef struct rexmpp_xml_qname rexmpp_xml_qname_t;
+typedef struct rexmpp_xml_attribute rexmpp_xml_attr_t;
+typedef struct rexmpp_xml_node rexmpp_xml_t;
+
+struct rexmpp_xml_qname {
+ char *name;
+ char *namespace;
+};
+
+struct rexmpp_xml_attribute {
+ rexmpp_xml_qname_t qname;
+ char *value;
+ rexmpp_xml_attr_t *next;
+};
+
+enum rexmpp_xml_node_type {
+ REXMPP_XML_ELEMENT,
+ REXMPP_XML_TEXT
+};
+
+typedef enum rexmpp_xml_node_type rexmpp_xml_node_type_t;
+
+struct rexmpp_xml_node {
+ rexmpp_xml_node_type_t type;
+ union {
+ struct {
+ rexmpp_xml_qname_t qname;
+ rexmpp_xml_attr_t *attributes;
+ rexmpp_xml_t *children;
+ } elem;
+ char *text;
+ } alt;
+ rexmpp_xml_t *next;
+};
+
+struct rexmpp_xml_builder {
+ rexmpp_xml_t *current;
+ rexmpp_xml_t *root;
+};
+
+void rexmpp_xml_qname_free (rexmpp_xml_qname_t *qname);
+void rexmpp_xml_attribute_free (rexmpp_xml_attr_t *attr);
+void rexmpp_xml_attribute_free_list (rexmpp_xml_attr_t *attr);
+
+/**
+ @brief Frees a single XML node. Does not free its siblings.
+*/
+void rexmpp_xml_free (rexmpp_xml_t *node);
+
+/**
+ @brief Frees an XML node and its siblings.
+*/
+void rexmpp_xml_free_list (rexmpp_xml_t *node);
+
+/**
+ @brief Clones a single XML node, without its siblings.
+*/
+rexmpp_xml_t *rexmpp_xml_clone (rexmpp_xml_t *node);
+
+/**
+ @brief Clones an XML node, together with its siblings.
+*/
+rexmpp_xml_t *rexmpp_xml_clone_list (rexmpp_xml_t *node);
+
+/**
+ @brief Creates a textual ::rexmpp_xml_t XML node (with type =
+ ::REXMPP_XML_TEXT).
+*/
+rexmpp_xml_t *rexmpp_xml_new_text (const char *str);
+
+/**
+ @brief Creates a textual ::rexmpp_xml_t XML node (with type =
+ ::REXMPP_XML_TEXT).
+*/
+rexmpp_xml_t *rexmpp_xml_new_text_len (const char *str, size_t len);
+
+/**
+ @brief Creates an element ::rexmpp_xml_t XML node (with type =
+ ::REXMPP_XML_ELEMENT).
+*/
+rexmpp_xml_t *rexmpp_xml_new_elem (const char *name,
+ const char *namespace);
+
+/**
+ @brief Adds a child node.
+*/
+void rexmpp_xml_add_child (rexmpp_xml_t *node,
+ rexmpp_xml_t *child);
+
+/**
+ @brief Creates a text node, and adds it as a child.
+*/
+int rexmpp_xml_add_text (rexmpp_xml_t *node,
+ const char *str);
+
+/**
+ @brief Creates a text node, and adds it as a child.
+*/
+int rexmpp_xml_add_text_len (rexmpp_xml_t *node,
+ const char *str,
+ size_t len);
+
+rexmpp_xml_attr_t *rexmpp_xml_attr_new (const char *name,
+ const char *namespace,
+ const char *value);
+
+int rexmpp_xml_add_attr (rexmpp_xml_t *node,
+ const char *name,
+ const char *value);
+
+int rexmpp_xml_remove_attr_ns (rexmpp_xml_t *node,
+ const char *name,
+ const char *namespace);
+
+int rexmpp_xml_remove_attr (rexmpp_xml_t *node,
+ const char *name);
+
+int rexmpp_xml_add_attr_ns (rexmpp_xml_t *node,
+ const char *name,
+ const char *namespace,
+ const char *value);
+
+/**
+ @brief Adds an "id" attribute to an XML stanza.
+ @param[in,out] s ::rexmpp
+ @param[in] node A pointer to an XML stanza.
+ @returns The same pointer as on input, for more convenient
+ composition.
+*/
+rexmpp_xml_t *
+rexmpp_xml_add_id (rexmpp_xml_t *node);
+
+/**
+ @brief A helper function for XML serialisation.
+ @param[in] node An XML node.
+ @returns A string (must be freed by the caller).
+*/
+char *rexmpp_xml_serialize (const rexmpp_xml_t *node, int pretty);
+
+/**
+ @brief Count the number of siblings after a given node.
+*/
+unsigned int rexmpp_xml_siblings_count (rexmpp_xml_t *node);
+
+/**
+ @brief Compares the node's name and namespace to given ones.
+*/
+int rexmpp_xml_match (rexmpp_xml_t *node,
+ const char *namespace,
+ const char *name);
+
+int rexmpp_xml_is_stanza (rexmpp_xml_t *node);
+
+/**
+ @brief Compose an 'error' element.
+*/
+rexmpp_xml_t *rexmpp_xml_error (const char *type, const char *condition);
+
+/**
+ @brief Matches an XML node against a namespace and an element name.
+ @param[in] node An XML node to match.
+ @param[in] namespace An XML namespace. Can be NULL (matches
+ anything), and it is assumed that the default namespace is
+ "jabber:client" (so if it is "jabber:client" and an element doesn't
+ have a namespace defined, this function counts that as a match).
+ @param[in] name Element name. Can be NULL (matches anything).
+ @returns 1 on a successful match, 0 otherwise.
+*/
+int rexmpp_xml_attr_match (rexmpp_xml_attr_t *attr,
+ const char *namespace,
+ const char *name);
+
+rexmpp_xml_attr_t *rexmpp_xml_find_attr (rexmpp_xml_t *node,
+ const char *name,
+ const char *namespace);
+
+const char *rexmpp_xml_find_attr_val_ns (rexmpp_xml_t *node,
+ const char *name,
+ const char *namespace);
+
+const char *rexmpp_xml_find_attr_val (rexmpp_xml_t *node,
+ const char *name);
+
+/**
+ @brief Finds a child element of an XML node, which matches the
+ given namespace and name.
+ @param[in] node The node containing child nodes.
+ @param[in] namespace The namespace to look for.
+ @param[in] name The element name to look for.
+ @returns A pointer to the first matching child node, or NULL if no
+ matching child elements found.
+*/
+rexmpp_xml_t *rexmpp_xml_find_child (rexmpp_xml_t *node,
+ const char *namespace,
+ const char *name);
+
+rexmpp_xml_t *rexmpp_xml_children (const rexmpp_xml_t *node);
+
+char *rexmpp_xml_text (rexmpp_xml_t *node);
+
+char *rexmpp_xml_text_child (rexmpp_xml_t *node);
+
+rexmpp_xml_t *rexmpp_xml_first_elem_child (rexmpp_xml_t *node);
+
+rexmpp_xml_t *rexmpp_xml_next_elem_sibling (rexmpp_xml_t *node);
+
+/**
+ @brief Compares two XML elements.
+*/
+int rexmpp_xml_eq (rexmpp_xml_t *n1, rexmpp_xml_t *n2);
+
+/**
+ @brief A helper function for XML parsing.
+ @param[in] str A string to parse.
+ @param[in] str_len String length.
+ @returns Parsed XML, or NULL on failure.
+*/
+rexmpp_xml_t *rexmpp_xml_parse (const char *str, int str_len);
+
+/**
+ @brief Reads XML from a file stream, reading the stream line by
+ line.
+ @param[in] fd A file descriptor
+ @returns Parsed XML, or NULL on failure.
+*/
+rexmpp_xml_t *rexmpp_xml_read_fd (int fd);
+
+/**
+ @brief Reads XML from a file
+ @param[in] path A file path
+ @returns Parsed XML, or NULL on failure.
+*/
+rexmpp_xml_t *rexmpp_xml_read_file (const char *path);
+
+/**
+ @brief Writes XML into a file
+ @param[in] path A file path
+ @param[in] node XML to write
+ @returns 0 on success, -1 on failure.
+*/
+int rexmpp_xml_write_file (const char *path, rexmpp_xml_t* node);
+
+/**
+ @brief Reverses a linked list of XML nodes
+ @param[in,out] node The head of the list to reverse
+ @returns The new head of the list
+*/
+rexmpp_xml_t *rexmpp_xml_reverse_list (rexmpp_xml_t *node);
+
+/**
+ @brief Recursively reverses children of an XML element
+ @param[in,out] node The root XML element
+*/
+void rexmpp_xml_reverse_children (rexmpp_xml_t *node);
+
+#endif