Browse Source

xml: Compilable expat module

Serj Kalichev 3 years ago
parent
commit
35ac611a25
1 changed files with 171 additions and 153 deletions
  1. 171 153
      klish/kdb/expat/expat_api.c

+ 171 - 153
klish/kdb/expat/expat_api.c

@@ -4,7 +4,7 @@
  *
  * This file implements the means to read an XML encoded file
  * and populate the CLI tree based on the contents. It implements
- * the clish_xml API using the expat XML parser
+ * the kxml_ API using the expat XML parser
  *
  * expat is not your typicall XML parser. It does not work
  * by creating a full in-memory XML tree, but by calling specific
@@ -21,6 +21,10 @@
  * ------------------------------------------------------
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -35,34 +39,39 @@
 #include <expat.h>
 #endif
 
-#include "xmlapi.h"
+#include <faux/faux.h>
+#include <faux/str.h>
+#include <klish/kxml.h>
+
 
 /** DOM_like XML node
  *
- * @struct clish_xmlnode_s
+ * @struct kxml_node_s
  */
-struct clish_xmlnode_s {
+struct kxml_node_s {
 	char *name;
-	clish_xmlnode_t *parent; /**< parent node */
-	clish_xmlnode_t *children; /**< list of children */
-	clish_xmlnode_t *next; /**< next sibling */
-	clish_xmlnode_t *attributes; /**< attributes are nodes too */
+	kxml_node_t *parent; /**< parent node */
+	kxml_node_t *children; /**< list of children */
+	kxml_node_t *next; /**< next sibling */
+	kxml_node_t *attributes; /**< attributes are nodes too */
 	char *content; /**< !NULL for text and attributes nodes */
-	clish_xmlnodetype_e type; /**< node type */
+	kxml_nodetype_e type; /**< node type */
 	int depth; /**< node depth */
-	clish_xmldoc_t *doc;
+	kxml_doc_t *doc;
 };
 
+
 /** DOM-like XML document
  *
- * @struct clish_xmldoc_s
+ * @struct kxml_doc_s
  */
-struct clish_xmldoc_s {
-	clish_xmlnode_t *root; /**< list of root elements */
-	clish_xmlnode_t *current; /**< current element */
+struct kxml_doc_s {
+	kxml_node_t *root; /**< list of root elements */
+	kxml_node_t *current; /**< current element */
 	char *filename; /**< current filename */
 };
 
+
 /*
  * Expat need these functions to be able to build a DOM-like tree that
  * will be usable by klish.
@@ -73,10 +82,10 @@ struct clish_xmldoc_s {
  * @param node element to add
  * @return new first element of the list
  */
-static clish_xmlnode_t *clish_expat_list_push_back(clish_xmlnode_t *first, clish_xmlnode_t *node)
+static kxml_node_t *kexpat_list_push_back(kxml_node_t *first, kxml_node_t *node)
 {
-	clish_xmlnode_t *cur = first;
-	clish_xmlnode_t *prev = NULL;
+	kxml_node_t *cur = first;
+	kxml_node_t *prev = NULL;
 
 	while (cur) {
 		prev = cur;
@@ -96,11 +105,11 @@ static clish_xmlnode_t *clish_expat_list_push_back(clish_xmlnode_t *first, clish
  * @param v attribute value
  * @return the new first attribute in the attribute list
  */
-static clish_xmlnode_t *clish_expat_add_attr(clish_xmlnode_t *first, const char *n, const char *v)
+static kxml_node_t *kexpat_add_attr(kxml_node_t *first, const char *n, const char *v)
 {
-	clish_xmlnode_t *node;
+	kxml_node_t *node = NULL;
 
-	node = malloc(sizeof(clish_xmlnode_t));
+	node = malloc(sizeof(kxml_node_t));
 	if (!node)
 		return first;
 
@@ -109,12 +118,13 @@ static clish_xmlnode_t *clish_expat_add_attr(clish_xmlnode_t *first, const char
 	node->children = NULL;
 	node->attributes = NULL;
 	node->next = NULL;
-	node->type = CLISH_XMLNODE_ATTR;
+	node->type = KXML_NODE_ATTR;
 	node->depth = 0;
 
-	return clish_expat_list_push_back(first, node);
+	return kexpat_list_push_back(first, node);
 }
 
+
 /** Run through an expat attribute list, and create a DOM-like attribute list
  *
  * @param node parent node
@@ -123,16 +133,17 @@ static clish_xmlnode_t *clish_expat_add_attr(clish_xmlnode_t *first, const char
  * Each attribute uses two slots in the expat attribute list. The first one is
  * used to store the name, the second one is used to store the value.
  */
-static void clish_expat_add_attrlist(clish_xmlnode_t *node, const char **attr)
+static void kexpat_add_attrlist(kxml_node_t *node, const char **attr)
 {
-	int i;
+	int i = 0;
 
 	for (i = 0; attr[i]; i += 2) {
-		node->attributes = clish_expat_add_attr(node->attributes,
+		node->attributes = kexpat_add_attr(node->attributes,
 			attr[i], attr[i+1]);
 	}
 }
 
+
 /** Generic make_node() function
  *
  * @param parent XML parent node
@@ -142,15 +153,15 @@ static void clish_expat_add_attrlist(clish_xmlnode_t *node, const char **attr)
  * @param attr attribute list
  * @return a new node or NULL on error
  */
-static clish_xmlnode_t *clish_expat_make_node(clish_xmlnode_t *parent,
-					      clish_xmlnodetype_e type,
-					      const char *n,
-					      const char *v,
-					      const char **attr)
+static kxml_node_t *kexpat_make_node(kxml_node_t *parent,
+	kxml_nodetype_e type,
+	const char *n,
+	const char *v,
+	const char **attr)
 {
-	clish_xmlnode_t *node;
+	kxml_node_t *node = NULL;
 
-	node = malloc(sizeof(clish_xmlnode_t));
+	node = malloc(sizeof(kxml_node_t));
 	if (!node)
 		return NULL;
 	node->name = n ? strdup(n) : NULL;
@@ -164,14 +175,15 @@ static clish_xmlnode_t *clish_expat_make_node(clish_xmlnode_t *parent,
 	node->type = type;
 
 	if (attr)
-		clish_expat_add_attrlist(node, attr);
+		kexpat_add_attrlist(node, attr);
 
 	if (parent)
-		parent->children = clish_expat_list_push_back(parent->children, node);
+		parent->children = kexpat_list_push_back(parent->children, node);
 
 	return node;
 }
 
+
 /** Add a new XML root
  *
  * @param doc XML document
@@ -179,19 +191,20 @@ static clish_xmlnode_t *clish_expat_make_node(clish_xmlnode_t *parent,
  * @param attr expat attribute list
  * @return a new root element
  */
-static clish_xmlnode_t *clish_expat_add_root(clish_xmldoc_t *doc, const char *el, const char **attr)
+static kxml_node_t *kexpat_add_root(kxml_doc_t *doc, const char *el, const char **attr)
 {
-	clish_xmlnode_t *node;
+	kxml_node_t *node = NULL;
 
-	node = clish_expat_make_node(NULL, CLISH_XMLNODE_ELM, el, NULL, attr);
+	node = kexpat_make_node(NULL, KXML_NODE_ELM, el, NULL, attr);
 	if (!node)
 		return doc->root;
 
-	doc->root = clish_expat_list_push_back(doc->root, node);
+	doc->root = kexpat_list_push_back(doc->root, node);
 
 	return node;
 }
 
+
 /** Add a new XML element as a child
  *
  * @param cur parent XML element
@@ -199,33 +212,34 @@ static clish_xmlnode_t *clish_expat_add_root(clish_xmldoc_t *doc, const char *el
  * @param attr expat attribute list
  * @return a new XMl element
  */
-static clish_xmlnode_t *clish_expat_add_child(clish_xmlnode_t *cur, const char *el, const char **attr)
+static kxml_node_t *kexpat_add_child(kxml_node_t *cur, const char *el, const char **attr)
 {
-	clish_xmlnode_t *node;
+	kxml_node_t *node;
 
-	node = clish_expat_make_node(cur, CLISH_XMLNODE_ELM, el, NULL, attr);
+	node = kexpat_make_node(cur, KXML_NODE_ELM, el, NULL, attr);
 	if (!node)
 		return cur;
 
 	return node;
 }
 
+
 /** Expat handler: element content
  *
  * @param data user data
  * @param s content (not nul-termainated)
  * @param len content length
  */
-static void clish_expat_chardata_handler(void *data, const char *s, int len)
+static void kexpat_chardata_handler(void *data, const char *s, int len)
 {
-	clish_xmldoc_t *doc = data;
+	kxml_doc_t *doc = data;
 
 	if (doc->current) {
 		char *content = malloc(len + 1);
 		strncpy(content, s, len);
 		content[len] = '\0';
 
-		clish_expat_make_node(doc->current, CLISH_XMLNODE_TEXT, NULL, content, NULL);
+		kexpat_make_node(doc->current, KXML_NODE_TEXT, NULL, content, NULL);
 		/*
 		 * the previous call is a bit too generic, and strdup() content
 		 * so we need to free out own version of content.
@@ -234,31 +248,33 @@ static void clish_expat_chardata_handler(void *data, const char *s, int len)
 	}
 }
 
+
 /** Expat handler: start XML element
  *
  * @param data user data
  * @param el element name (nul-terminated)
  * @param attr expat attribute list
  */
-static void clish_expat_element_start(void *data, const char *el, const char **attr)
+static void kexpat_element_start(void *data, const char *el, const char **attr)
 {
-	clish_xmldoc_t *doc = data;
+	kxml_doc_t *doc = data;
 
 	if (!doc->current) {
-		doc->current = clish_expat_add_root(doc, el, attr);
+		doc->current = kexpat_add_root(doc, el, attr);
 	} else {
-		doc->current = clish_expat_add_child(doc->current, el, attr);
+		doc->current = kexpat_add_child(doc->current, el, attr);
 	}
 }
 
+
 /** Expat handler: end XML element
  *
  * @param data user data
  * @param el element name
  */
-static void clish_expat_element_end(void *data, const char *el)
+static void kexpat_element_end(void *data, const char *el)
 {
-	clish_xmldoc_t *doc = data;
+	kxml_doc_t *doc = data;
 
 	if (doc->current) {
 		doc->current = doc->current->parent;
@@ -267,21 +283,22 @@ static void clish_expat_element_end(void *data, const char *el)
 	el = el; /* Happy compiler */
 }
 
+
 /** Free a node, its children and its attributes
  *
  * @param node node to free
  */
-static void clish_expat_free_node(clish_xmlnode_t *cur)
+static void kexpat_free_node(kxml_node_t *cur)
 {
-	clish_xmlnode_t *node;
-	clish_xmlnode_t *first;
+	kxml_node_t *node;
+	kxml_node_t *first;
 
 	if (cur->attributes) {
 		first = cur->attributes;
 		while (first) {
 			node = first;
 			first = first->next;
-			clish_expat_free_node(node);
+			kexpat_free_node(node);
 		}
 	}
 	if (cur->children) {
@@ -289,7 +306,7 @@ static void clish_expat_free_node(clish_xmlnode_t *cur)
 		while (first) {
 			node = first;
 			first = first->next;
-			clish_expat_free_node(node);
+			kexpat_free_node(node);
 		}
 	}
 	if (cur->name)
@@ -303,38 +320,40 @@ static void clish_expat_free_node(clish_xmlnode_t *cur)
  * Public interface
  */
 
-int clish_xmldoc_start(void)
+int kxml_doc_start(void)
 {
 	return 0;
 }
 
-int clish_xmldoc_stop(void)
+
+int kxml_doc_stop(void)
 {
 	return 0;
 }
 
-clish_xmldoc_t *clish_xmldoc_read(const char *filename)
+
+kxml_doc_t *kxml_doc_read(const char *filename)
 {
-	clish_xmldoc_t *doc;
-	struct stat sb;
-	int fd;
-	char *buffer;
+	kxml_doc_t *doc = NULL;
+	struct stat sb = {};
+	int fd = -1;
+	char *buffer = NULL;
 	XML_Parser parser;
-	int rb;
+	int rb = 0;
 
-	doc = malloc(sizeof(clish_xmldoc_t));
+	doc = malloc(sizeof(kxml_doc_t));
 	if (!doc)
 		return NULL;
-	memset(doc, 0, sizeof(clish_xmldoc_t));
+	memset(doc, 0, sizeof(kxml_doc_t));
 	doc->filename = strdup(filename);
 	parser = XML_ParserCreate(NULL);
 	if (!parser)
 		goto error_parser_create;
 	XML_SetUserData(parser, doc);
-	XML_SetCharacterDataHandler(parser, clish_expat_chardata_handler);
+	XML_SetCharacterDataHandler(parser, kexpat_chardata_handler);
 	XML_SetElementHandler(parser,
-		clish_expat_element_start,
-		clish_expat_element_end);
+		kexpat_element_start,
+		kexpat_element_end);
 
 	fd = open(filename, O_RDONLY);
 	if (fd < 0)
@@ -364,19 +383,20 @@ error_open:
 	XML_ParserFree(parser);
 
 error_parser_create:
-	clish_xmldoc_release(doc);
+	kxml_doc_release(doc);
 
 	return NULL;
 }
 
-void clish_xmldoc_release(clish_xmldoc_t *doc)
+
+void kxml_doc_release(kxml_doc_t *doc)
 {
 	if (doc) {
-		clish_xmlnode_t *node;
+		kxml_node_t *node;
 		while (doc->root) {
 			node = doc->root;
 			doc->root = node->next;
-			clish_expat_free_node(node);
+			kexpat_free_node(node);
 		}
 		if (doc->filename)
 			free(doc->filename);
@@ -384,149 +404,147 @@ void clish_xmldoc_release(clish_xmldoc_t *doc)
 	}
 }
 
-int clish_xmldoc_is_valid(clish_xmldoc_t *doc)
+
+int kxml_doc_is_valid(const kxml_doc_t *doc)
 {
-	return doc && doc->root;
+	return (doc && doc->root);
 }
 
-int clish_xmldoc_error_caps(clish_xmldoc_t *doc)
+/*
+int kxml_doc_error_caps(kxml_doc_t *doc)
 {
-	doc = doc; /* Happy compiler */
+	doc = doc; // Happy compiler
 
-	return CLISH_XMLERR_NOCAPS;
+	return kxml_ERR_NOCAPS;
 }
 
-int clish_xmldoc_get_err_line(clish_xmldoc_t *doc)
+int kxml_doc_get_err_line(kxml_doc_t *doc)
 {
-	doc = doc; /* Happy compiler */
+	doc = doc; // Happy compiler
 
 	return -1;
 }
 
-int clish_xmldoc_get_err_col(clish_xmldoc_t *doc)
+int kxml_doc_get_err_col(kxml_doc_t *doc)
 {
-	doc = doc; /* Happy compiler */
+	doc = doc; // Happy compiler
 
 	return -1;
 }
 
-const char *clish_xmldoc_get_err_msg(clish_xmldoc_t *doc)
+const char *kxml_doc_get_err_msg(kxml_doc_t *doc)
 {
-	doc = doc; /* Happy compiler */
+	doc = doc; // Happy compiler
 
 	return "";
 }
+*/
 
-int clish_xmlnode_get_type(clish_xmlnode_t *node)
+kxml_nodetype_e kxml_node_type(const kxml_node_t *node)
 {
 	if (node)
 		return node->type;
-	return CLISH_XMLNODE_UNKNOWN;
+
+	return KXML_NODE_UNKNOWN;
 }
 
-clish_xmlnode_t *clish_xmldoc_get_root(clish_xmldoc_t *doc)
+
+kxml_node_t *kxml_doc_root(const kxml_doc_t *doc)
 {
 	if (doc)
 		return doc->root;
+
 	return NULL;
 }
 
-clish_xmlnode_t *clish_xmlnode_parent(clish_xmlnode_t *node)
+
+kxml_node_t *kxml_node_parent(const kxml_node_t *node)
 {
 	if (node)
 		return node->parent;
+
 	return NULL;
 }
 
-clish_xmlnode_t *clish_xmlnode_next_child(clish_xmlnode_t *parent,
-					  clish_xmlnode_t *curchild)
+
+const kxml_node_t *kxml_node_next_child(const kxml_node_t *parent,
+	const kxml_node_t *curchild)
 {
 	if (curchild)
 		return curchild->next;
 	if (parent)
 		return parent->children;
+
 	return NULL;
 }
 
-char *clish_xmlnode_fetch_attr(clish_xmlnode_t *node,
-			       const char *attrname)
+
+char *kxml_node_attr(const kxml_node_t *node,
+	const char *attrname)
 {
-	if (node) {
-		clish_xmlnode_t *n = node->attributes;
-		while (n) {
-			if (strcmp(n->name, attrname) == 0)
-				return n->content;
-			n = n->next;
-		}
+	kxml_node_t *n = NULL;
+
+	if (!node)
+		return NULL;
+
+	n = node->attributes;
+	while (n) {
+		if (strcmp(n->name, attrname) == 0)
+			return n->content;
+		n = n->next;
 	}
+
 	return NULL;
 }
 
-int clish_xmlnode_get_content(clish_xmlnode_t *node, char *content,
-			      unsigned int *contentlen)
-{
-	unsigned int minlen = 1;
-
-	if (node && content && contentlen) {
-		clish_xmlnode_t *children = node->children;
-		while (children) {
-			if (children->type == CLISH_XMLNODE_TEXT && children->content)
-				minlen += strlen(children->content);
-			children = children->next;
-		}
-		if (minlen >= *contentlen) {
-			*contentlen = minlen + 1;
-			return -E2BIG;
-		}
-		children = node->children;
-		*content = 0;
-		while (children) {
-			if (children->type == CLISH_XMLNODE_TEXT && children->content)
-				strcat(content, children->content);
-			children = children->next;
-		}
-		return 0;
-	}
 
-	return -EINVAL;
+void kxml_node_attr_free(char *str)
+{
+	str = str; // Happy compiler
+	// kxml_node_attr() doesn't allocate any memory
+	// so we don't need to free()
 }
 
-int clish_xmlnode_get_name(clish_xmlnode_t *node, char *name,
-	unsigned int *namelen)
+
+char *kxml_node_content(const kxml_node_t *node)
 {
-	if (node && name && namelen) {
-		if (strlen(node->name) >= *namelen) {
-			*namelen = strlen(node->name) + 1;
-			return -E2BIG;
-		}
-		snprintf(name, *namelen, "%s", node->name);
-		name[*namelen - 1] = '\0';
-		return 0;
+	char *content = NULL;
+	kxml_node_t *children = NULL;
+
+	if (!node)
+		return NULL;
+
+	children = node->children;
+	while (children) {
+		if (children->type == KXML_NODE_TEXT && children->content)
+			faux_str_cat(&content, children->content);
+		children = children->next;
 	}
-	return -EINVAL;
+
+	return content;
 }
 
-void clish_xmlnode_print(clish_xmlnode_t *node, FILE *out)
+
+void kxml_node_content_free(char *str)
 {
-	if (node) {
-		int i;
-		clish_xmlnode_t *a;
-		for (i=0; i<node->depth; ++i) {
-			fprintf(out, "  ");
-		}
-		fprintf(out, "<%s", node->name);
-		a = node->attributes;
-		while (a) {
-			fprintf(out, " %s='%s'", a->name, a->content);
-			a = a->next;
-		}
-		fprintf(out, ">...");
-	}
+	if (!str)
+		return;
+	faux_str_free(str);
 }
 
-void clish_xml_release(void *p)
+
+char *kxml_node_name(const kxml_node_t *node)
 {
-	p = p; /* Happy compiler */
-	/* nothing to release */
+	if (!node)
+		return NULL;
+
+	return node->name;
 }
 
+
+void kxml_node_name_free(char *str)
+{
+	str = str; // Happy compiler
+	// kxml_node_attr() doesn't allocate any memory
+	// so we don't need to free()
+}