#include "StdAfx.h"
#ifndef ACL_PREPARE_COMPILE

#include <string.h>
#include <stdio.h>
#include "stdlib/acl_msg.h"
#include "stdlib/acl_mystring.h"
#include "stdlib/acl_define.h"
#include "stdlib/acl_mymalloc.h"
#include "stdlib/acl_dbuf_pool.h"
#include "xml/acl_xml3.h"

#endif

#define	LEN	ACL_VSTRING_LEN
#define	STR	acl_vstring_str

ACL_XML3_ATTR *acl_xml3_attr_alloc(ACL_XML3_NODE *node)
{
	ACL_XML3_ATTR *attr = (ACL_XML3_ATTR*)
		acl_dbuf_pool_calloc(node->xml->dbuf, sizeof(ACL_XML3_ATTR));

	attr->node       = node;
	attr->name       = node->xml->addr;
	attr->name_size  = 0;
	attr->value      = node->xml->addr;
	attr->value_size = 0;
	attr->quote      = 0;
	attr->backslash  = 0;

	acl_array_append(node->attr_list, attr);

	return attr;
}

static ACL_XML3_NODE *node_iter_head(ACL_ITER *it, ACL_XML3_NODE *node)
{
	ACL_RING *ring_ptr;

	it->dlen = -1;
	it->key = NULL;
	it->klen = -1;

	it->i = 0;
	it->size = node->children.len;

	if ((ring_ptr = acl_ring_succ(&node->children)) == &node->children) {
		it->ptr = it->data = NULL;
		return NULL;
	}

	it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
	it->data = it->ptr;

	return it->ptr;
}

static ACL_XML3_NODE *node_iter_next(ACL_ITER *it, ACL_XML3_NODE *node)
{
	ACL_RING *ring_ptr;
	struct ACL_XML3_NODE *child = (struct ACL_XML3_NODE*) it->data;

	if ((ring_ptr = acl_ring_succ(&child->node)) == &node->children) {
		it->ptr = it->data = NULL;
		return NULL;
	}

	it->i++;
	it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
	it->data = it->ptr;

	return it->ptr;
}

static ACL_XML3_NODE *node_iter_tail(ACL_ITER *it, ACL_XML3_NODE *node)
{
	ACL_RING *ring_ptr;

	it->dlen = -1;
	it->key = NULL;
	it->klen = -1;

	it->i = 0;
	it->size = node->children.len;

	if ((ring_ptr = acl_ring_pred(&node->children)) == &node->children) {
		it->ptr = it->data = NULL;
		return NULL;
	}

	it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
	it->data = it->ptr;

	return it->ptr;
}

static ACL_XML3_NODE *node_iter_prev(ACL_ITER *it, ACL_XML3_NODE *node)
{
	ACL_RING *ring_ptr;
	struct ACL_XML3_NODE *child = (struct ACL_XML3_NODE*) it->data;

	if ((ring_ptr = acl_ring_pred(&child->node)) == &node->children) {
		it->ptr = it->data = NULL;
		return NULL;
	}

	it->i++;
	it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
	it->data = it->ptr;

	return it->ptr;
}

ACL_XML3_NODE *acl_xml3_node_alloc(ACL_XML3 *xml)
{
	ACL_XML3_NODE *node = (ACL_XML3_NODE*)
		acl_dbuf_pool_calloc(xml->dbuf, sizeof(ACL_XML3_NODE));

	acl_ring_init(&node->children);
	acl_ring_init(&node->node);

	node->xml       = xml;
	node->status    = ACL_XML3_S_NXT;
	node->ltag      = xml->addr;
	node->rtag      = xml->addr;
	node->ltag_size = 0;
	node->rtag_size = 0;

	node->text      = xml->addr;
	node->text_size = 0;
	node->attr_list = acl_array_dbuf_create(100, xml->dbuf);

	node->iter_head = node_iter_head;
	node->iter_next = node_iter_next;
	node->iter_tail = node_iter_tail;
	node->iter_prev = node_iter_prev;

	return node;
}

int acl_xml3_node_delete(ACL_XML3_NODE *node)
{
	ACL_RING *next;
	ACL_XML3_NODE *node_next;
	int   n = 1;

	while ((next = acl_ring_pop_head(&node->children)) != NULL) {
		node_next = acl_ring_to_appl(next, ACL_XML3_NODE, node);
		n += acl_xml3_node_delete(node_next);
	}

	if (node->id != NULL)
		acl_htable_delete(node->xml->id_table, node->id, NULL);

	acl_ring_detach(&node->node);
	node->xml->node_cnt--;

	return n;
}

void acl_xml3_node_append(ACL_XML3_NODE *node1, ACL_XML3_NODE *node2)
{
	acl_ring_append(&node1->node, &node2->node);
	node2->parent = node1->parent;
	node1->xml->node_cnt++;
}

void acl_xml3_node_add_child(ACL_XML3_NODE *parent, ACL_XML3_NODE *child)
{
	acl_ring_prepend(&parent->children, &child->node);
	child->parent = parent;
	parent->xml->node_cnt++;
}

ACL_XML3_NODE *acl_xml3_node_parent(ACL_XML3_NODE *node)
{
	return node->parent;
}

ACL_XML3_NODE *acl_xml3_node_next(ACL_XML3_NODE *node)
{
	ACL_RING *ring_ptr = acl_ring_succ(&node->node);
	ACL_XML3_NODE *parent;

	if (ring_ptr == &node->node)
		return NULL;

	parent = node->parent;
	acl_assert(parent != NULL);
	if (ring_ptr == &parent->children)
		return NULL;

	return acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
}

ACL_XML3_NODE *acl_xml3_node_prev(ACL_XML3_NODE *node)
{
	ACL_RING *ring_ptr = acl_ring_pred(&node->node);
	ACL_XML3_NODE *parent;

	if (ring_ptr == &node->node)
		return NULL;
	parent = node->parent;
	acl_assert(parent != NULL);
	if (ring_ptr == &parent->children)
		return NULL;

	return acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
}

static ACL_XML3_NODE *xml_iter_head(ACL_ITER *it, ACL_XML3 *xml)
{
	ACL_RING *ring_ptr;

	it->dlen = -1;
	it->key = NULL;
	it->klen = -1;

	it->i = 0;
	it->size = xml->node_cnt;

	ring_ptr = acl_ring_succ(&xml->root->children);
	if (ring_ptr== &xml->root->children) {
		it->ptr = it->data = NULL;
		return NULL;
	}

	it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
	it->data = it->ptr;

	return it->ptr;
}

static ACL_XML3_NODE *xml_iter_next(ACL_ITER *it, ACL_XML3 *xml)
{
	ACL_RING *ring_ptr;
	struct ACL_XML3_NODE *node, *parent;

	node = (struct ACL_XML3_NODE*) it->data;

	/* 先遍历当前节点的子节点 */

	ring_ptr = acl_ring_succ(&node->children);
	if (ring_ptr != &node->children) {
		it->i++;
		it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
		it->data = it->ptr;
		return it->ptr;
	}

	/* 当前节点的子节点遍历完毕，再遍历当前节点的兄弟节点 */

	parent = acl_xml3_node_parent(node);
	ring_ptr = acl_ring_succ(&node->node);
	if (ring_ptr != &parent->children) {
		it->i++;
		it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
		it->data = it->ptr;
		return it->ptr;
	}

	/* 当前节点的兄弟节点遍历完毕，最后遍历当前节点的父节点的兄弟节点 */

	do {
		if (parent == xml->root)
			break;

		ring_ptr = acl_ring_succ(&parent->node);
		parent = acl_xml3_node_parent(parent);
		if (parent == NULL)
			acl_msg_fatal("%s(%d): parent null",
				__FILE__, __LINE__);

		if (ring_ptr != &parent->children) {
			it->i++;
			it->ptr = acl_ring_to_appl(ring_ptr,
					ACL_XML3_NODE, node);
			it->data = it->ptr;
			return it->ptr;
		}
	} while (ring_ptr != &xml->root->children);

	/* 遍历完所有节点 */

	it->ptr = it->data = NULL;
	return NULL;
}

static ACL_XML3_NODE *xml_iter_tail(ACL_ITER *it, ACL_XML3 *xml)
{
	ACL_RING *ring_ptr;

	it->dlen = -1;
	it->key = NULL;
	it->klen = -1;

	it->i = 0;
	it->size = xml->node_cnt;

	ring_ptr = acl_ring_pred(&xml->root->children);
	if (ring_ptr== &xml->root->children) {
		it->ptr = it->data = NULL;
		return NULL;
	}
	it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
	it->data = it->ptr;
	return it->ptr;
}

static ACL_XML3_NODE *xml_iter_prev(ACL_ITER *it, ACL_XML3 *xml)
{
	ACL_RING *ring_ptr;
	struct ACL_XML3_NODE *node, *parent;

	node = (struct ACL_XML3_NODE*) it->data;

	/* 先遍历当前节点的子节点 */

	ring_ptr = acl_ring_pred(&node->children);
	if (ring_ptr != &node->children) {
		it->i++;
		it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
		it->data = it->ptr;
		return it->ptr;
	}

	/* 当前节点的子节点遍历完毕，再遍历当前节点的兄弟节点 */

	parent = acl_xml3_node_parent(node);
	ring_ptr = acl_ring_pred(&node->node);
	if (ring_ptr != &parent->children) {
		it->i++;
		it->ptr = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);
		it->data = it->ptr;
		return it->ptr;
	}

	/* 当前节点的兄弟节点遍历完毕，最后遍历当前节点的父节点的兄弟节点 */

	do {
		if (parent == xml->root)
			break;
		ring_ptr = acl_ring_pred(&parent->node);
		parent = acl_xml3_node_parent(parent);
		if (parent == NULL)
			acl_msg_fatal("%s(%d): parent null",
				__FILE__, __LINE__);

		if (ring_ptr != &parent->children) {
			it->i++;
			it->ptr = acl_ring_to_appl(ring_ptr,
					ACL_XML3_NODE, node);
			it->data = it->ptr;
			return it->ptr;
		}
	} while (ring_ptr != &xml->root->children);

	/* 遍历完所有节点 */

	it->ptr = it->data = NULL;
	return NULL;
}

void acl_xml3_multi_root(ACL_XML3 *xml, int on)
{
	if (on)
		xml->flag |= ACL_XML3_FLAG_MULTI_ROOT;
	else
		xml->flag &= ~ACL_XML3_FLAG_MULTI_ROOT;
}

void acl_xml3_slash(ACL_XML3 *xml, int ignore)
{
	if (ignore)
		xml->flag |= ACL_XML3_FLAG_IGNORE_SLASH;
	else
		xml->flag &=~ACL_XML3_FLAG_IGNORE_SLASH;
}

ACL_XML3 *acl_xml3_alloc()
{
	return acl_xml3_dbuf_alloc(NULL);
}

ACL_XML3 *acl_xml3_dbuf_alloc(ACL_DBUF_POOL *dbuf)
{
	ACL_XML3 *xml;

	if (dbuf == NULL) {
		dbuf = acl_dbuf_pool_create(8192);
		xml = (ACL_XML3*) acl_dbuf_pool_calloc(dbuf, sizeof(ACL_XML3));
		xml->dbuf_inner = dbuf;
	} else {
		xml = (ACL_XML3*) acl_dbuf_pool_calloc(dbuf, sizeof(ACL_XML3));
		xml->dbuf_inner = NULL;
	}

	xml->dbuf      = dbuf;
	xml->dbuf_keep = sizeof(ACL_XML3);
	xml->addr[0]   = '\0';
	xml->flag     |= ACL_XML3_FLAG_MULTI_ROOT;

	xml->iter_head = xml_iter_head;
	xml->iter_next = xml_iter_next;
	xml->iter_tail = xml_iter_tail;
	xml->iter_prev = xml_iter_prev;

	xml->id_table  = acl_htable_create(100, 0);
	xml->root      = acl_xml3_node_alloc(xml);
	xml->node_cnt  = 1;

	return xml;
}

int acl_xml3_free(ACL_XML3 *xml)
{
	int  node_cnt = xml->node_cnt;

	acl_htable_free(xml->id_table, NULL);

	if (xml->dbuf_inner != NULL)
		acl_dbuf_pool_destroy(xml->dbuf_inner);

	return node_cnt - 1;
}

void acl_xml3_reset(ACL_XML3 *xml)
{
	acl_htable_reset(xml->id_table, NULL);

	if (xml->dbuf_inner != NULL)
		acl_dbuf_pool_reset(xml->dbuf_inner, xml->dbuf_keep);

	xml->root      = acl_xml3_node_alloc(xml);
	xml->depth     = 0;
	xml->node_cnt  = 1;
	xml->root_cnt  = 0;
	xml->curr_node = NULL;
}

void acl_xml3_foreach_init(ACL_XML3 *xml, ACL_XML3_NODE *node)
{
	xml->root = node;
	xml->iter_head = xml_iter_head;
	xml->iter_next = xml_iter_next;
	xml->iter_tail = xml_iter_tail;
	xml->iter_prev = xml_iter_prev;
}

int acl_xml3_is_closure(ACL_XML3 *xml)
{
	ACL_RING *ring_ptr;
	ACL_XML3_NODE *node;

	/* 获得 xml->root 节点的最后一个一级子节点 */
	ring_ptr = acl_ring_succ(&xml->root->children);

	if (ring_ptr == &xml->root->children) {
		/* 说明没有真实子节点 */
		return 0;
	}

	node = acl_ring_to_appl(ring_ptr, ACL_XML3_NODE, node);

	if ((node->flag & ACL_XML3_F_SELF_CL)) {
		/* 说明该节点是自闭合节点 */
		return 1;
	}

	if (node->status == ACL_XML3_S_RGT) {
		return 1;
	}

	/* 说明最后一个一级子节点还未处理完毕 */
	return 0;
}

int acl_xml3_is_complete(ACL_XML3 *xml, const char *tag)
{
	ACL_XML3_NODE *last_node = NULL;
	ACL_ITER iter;

	if (!(xml->flag & ACL_XML3_FLAG_MULTI_ROOT) && xml->root_cnt > 0)
		return 1;

	acl_foreach_reverse(iter, xml->root) {
		ACL_XML3_NODE *node = (ACL_XML3_NODE*) iter.data;
		if (!(node->flag & ACL_XML3_F_META)) {
			last_node = node;
			break;
		}
	}

	if (last_node == NULL)
		/* 说明没有真实子节点 */
		return 0;

	if ((last_node->flag & ACL_XML3_F_SELF_CL))
		/* 说明该节点是自闭合节点 */
		return 1;

	if (last_node->status != ACL_XML3_S_RGT)
		/* 说明最后一个一级子节点还未处理完毕 */
		return 0;

	if (strcasecmp(last_node->rtag, tag) == 0)
		return 1;

	/* 说明 xml 中的最后一个节点与所给标签不匹配 */
	return 0;
}
