Signed-off-by: Xu Wang <gesaint(a)linux.vnet.ibm.com>
---
libxkutil/device_parsing.c | 200 +++++++++++++++++++++++++++++++++++++++++++-
libxkutil/device_parsing.h | 21 +++++
2 files changed, 219 insertions(+), 2 deletions(-)
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
index ea84d07..09dab97 100644
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -52,7 +52,7 @@
/* Device parse function */
typedef int (*dev_parse_func_t)(xmlNode *, struct virt_device **);
-static void cleanup_node_of_others(struct others *others)
+void cleanup_node_of_others(struct others *others)
{
if (others == NULL) {
return;
@@ -73,7 +73,7 @@ static void cleanup_node_of_others(struct others *others)
free(others);
}
-static void cleanup_others(struct others *others)
+void cleanup_others(struct others *others)
{
struct others *head = others;
@@ -254,6 +254,202 @@ char *get_node_content(xmlNode *node)
return buf;
}
+void print_others(struct others *head)
+{
+ while (head) {
+ CU_DEBUG("---------------------------");
+ CU_DEBUG("- others name: %s", head->name);
+ CU_DEBUG("- others value: %s", head->value);
+ CU_DEBUG("- others type: %d", head->type);
+ CU_DEBUG("- others parent: %s", head->parent);
+ CU_DEBUG("---------------------------");
+ head = head->next;
+ }
+}
+
+struct others *add_others(struct others *head,
+ xmlNode *node,
+ const xmlChar *name,
+ enum others_type type,
+ const xmlChar *parent)
+{
+ struct others *new = NULL;
+
+ new = calloc(1, sizeof(*new));
+ if (new == NULL) {
+ CU_DEBUG("calloc space failed.");
+ return NULL;
+ }
+
+ new->name = strdup((char *)name);
+ if (parent) {
+ new->parent = strdup((char *)parent);
+ }
+ new->type = type;
+ if (type == TYPE_PROP) {
+ new->value = get_attr_value(node, (char *)name);
+ } else if (type == TYPE_NODE) {
+ new->value = get_node_content(node);
+ }
+ new->next = NULL;
+
+ if (head == NULL) {
+ head = new;
+ } else {
+ new->next = head;
+ head = new;
+ }
+
+ return head;
+}
+
+bool compare_parent(const char *a, const char *b)
+{
+ if ((a == NULL) && (b == NULL)) {
+ return true;
+ }
+
+ if ((a != NULL) && (b != NULL) &&
+ STREQ(a, b)) {
+ return true;
+ }
+
+ return false;
+}
+
+char *fetch_from_others(struct others **head,
+ char *name,
+ enum others_type type,
+ char *parent)
+{
+ struct others *tmp = *head;
+ struct others *last = NULL;
+ char *value = NULL;
+
+ while (tmp) {
+ if (STREQ(tmp->name, name) &&
+ compare_parent(tmp->parent, parent) &&
+ tmp->type == type) {
+ value = strdup(tmp->value);
+ if (tmp == *head) {
+ /* The first node is we needed. */
+ if ((*head)->next) {
+ /* There are more than two nodes in others. */
+ *head = (*head)->next;
+ } else {
+ *head = NULL;
+ }
+ } else {
+ last->next = tmp->next;
+ }
+ cleanup_node_of_others(tmp);
+ return value;
+ }
+ last = tmp;
+ tmp = tmp->next;
+ }
+
+ return NULL;
+}
+
+static bool seek_in_others(struct others **head,
+ char *name,
+ enum others_type type,
+ char *parent)
+{
+ struct others *tmp = *head;
+ struct others *last = NULL;
+
+ while (tmp) {
+ if (STREQ(tmp->name, name) &&
+ compare_parent(tmp->parent, parent) &&
+ tmp->type == type) {
+ if (tmp == *head) {
+ if (tmp->next) {
+ *head = (*head)->next;
+ } else {
+ *head = NULL;
+ }
+ } else {
+ last->next = tmp->next;
+ }
+ cleanup_node_of_others(tmp);
+
+ return true;
+ }
+ last = tmp;
+ tmp = tmp->next;
+ }
+
+ return false;
+}
+
+struct others *combine_others(struct others *head1,
+ struct others *head2)
+{
+ struct others *tail1 = head1;
+
+ if (tail1 == NULL) {
+ return head2;
+ }
+
+ while (tail1->next) {
+ tail1 = tail1->next;
+ }
+
+ tail1->next = head2;
+ return head1;
+}
+
+static struct others *parse_data_to_others(xmlNode *node, const xmlChar *parent)
+{
+ xmlNode *child = NULL;
+ xmlAttrPtr attrPtr = NULL;
+ struct others *head = NULL;
+ struct others *head2 = NULL;
+
+ /* If name of node is "text", all operations will skip */
+ if (XSTREQ(node->name, "text")) {
+ return NULL;
+ }
+
+ head = add_others(head,
+ node,
+ node->name,
+ TYPE_NODE,
+ parent);
+
+ if (head == NULL) {
+ goto err;
+ }
+
+ /* Get properties of node */
+ attrPtr = node->properties;
+ while (attrPtr) {
+ head = add_others(head,
+ node,
+ attrPtr->name,
+ TYPE_PROP,
+ node->name);
+ if (head == NULL) {
+ goto err;
+ }
+
+ attrPtr = attrPtr->next;
+ }
+
+ for (child = node->children; child != NULL; child = child->next) {
+ /* Recursion to restore child's properties or child if have */
+ head2 = parse_data_to_others(child, node->name);
+ head = combine_others(head, head2);
+ }
+
+ return head;
+err:
+ CU_DEBUG("add_others failed.");
+ return NULL;
+}
+
static int parse_fs_device(xmlNode *dnode, struct virt_device **vdevs)
{
struct virt_device *vdev = NULL;
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
index 027dd21..166f305 100644
--- a/libxkutil/device_parsing.h
+++ b/libxkutil/device_parsing.h
@@ -258,6 +258,27 @@ int change_device(virDomainPtr dom, struct virt_device *dev);
bool has_kvm_domain_type(xmlNodePtr node);
+struct others *add_others(struct others *head,
+ xmlNode *node,
+ const xmlChar *name,
+ enum others_type type,
+ const xmlChar *parent);
+
+char *fetch_from_others(struct others **head,
+ char *name,
+ enum others_type type,
+ char *parent);
+
+void cleanup_node_of_others(struct others *others);
+
+bool compare_parent(const char *a, const char *b);
+
+void print_others(struct others *head);
+
+void cleanup_others(struct others *others);
+
+struct others *combine_others(struct others *head1, struct others *head2);
+
#define XSTREQ(x, y) (STREQ((char *)x, y))
#define STRPROP(d, p, n) (d->p = get_node_content(n))
--
1.7.1