
Signed-off-by: Xu Wang <gesaint@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