#include "platform.h"
#ifdef SIEMENS
  #include <swilib.h>
#else
  #include <string.h>
  #include <stdlib.h>
  #include <sys/types.h>
  #include <stdio.h>

  #include "siemens_compat.h"
#endif

#include <strings.h>
#include "string_util.h"
#include "xml_common.h"
#include "xml_gen.h"

XMLNode *
XML_CreateNode(char *name, char *value)
{
	XMLNode *node;

	if (name==NULL)
		return NULL;

	node = malloc(sizeof(XMLNode));
	bzero(node, sizeof(XMLNode));
	node->name = malloc(strlen(name) + 1);
	strcpy(node->name, name);
	if (value) {
		node->value = malloc(strlen(value) + 1);
		strcpy(node->value, value);
	}

	return (node);
}

int
XML_Set_Attr_Value(XMLNode *node, char *attr_name, char *attr_value)
{
	XMLAttr *p, **tail;
	u_int32_t len;

	if (!node || !attr_name)
		return (-1);
	tail = NULL;
	if (node->attr) {
		p = node->attr;
		while (p) {
			if (!strcmp(p->name, attr_name)) {
				len = strlen(attr_value);
				p->param = realloc(p->param, len + 1);
				strcpy(p->param, attr_value);
				break;
			}
			p = p->next;
		}

		if (!p) {/* No attr with such name */
			p = node->attr;
			while (p->next) {
				p = p->next;
			}
			tail = (XMLAttr**)&(p->next);

		}
	} else tail = &(node->attr);

	if (tail) {
		p = malloc(sizeof(XMLAttr));
		bzero(p, sizeof(XMLAttr));
		p->name = malloc(strlen(attr_name)+1);
		p->param= malloc(strlen(attr_value)+1);
		strcpy(p->name, attr_name);
		strcpy(p->param, attr_value);
		*tail = p;
	}
	return (0);
}

static inline char *
chk_realloc_buf(char *buf, u_int32_t * buf_len, u_int32_t remain, u_int32_t growsize)
{
	u_int32_t l_buf_len;
	l_buf_len = *buf_len;

	if (growsize > remain - 100) {
		buf = realloc(buf, l_buf_len+=growsize+1024);
		*buf_len = l_buf_len;
	}

	return (buf);
}

char *
XML_Get_Node_As_Text(XMLNode *node)
{
	XMLAttr *attr;
	char *buf, *sub_buf, *conv_param;
	u_int32_t buf_len, occ_len, l;
	XMLNode *sn;

#define CHK(b, l) b = chk_realloc_buf(b, &buf_len, buf_len - occ_len, l);

	if (!node || !node->name) /* Check sanity */
		return (NULL);

	occ_len = 0;
	buf = malloc(buf_len = 1024);
	bzero(buf, buf_len);
	buf[occ_len++]='<';
	strncpy(buf + occ_len, node->name, buf_len - occ_len);
	l = strlen(node->name);
	occ_len+=l;

	/* Copy attributes */
	attr = node->attr;
	while (attr && attr->name && attr->param) {
		buf[occ_len++]=' ';
		l = strlen(attr->name);
		CHK(buf, l);
		strncpy(buf + occ_len, attr->name, buf_len - occ_len);
		occ_len+=l;
		buf[occ_len++]='=';
		buf[occ_len++]='"';
		conv_param = Mask_Special_Syms(attr->param);
		l = strlen(conv_param);
		CHK(buf, l);
		strncpy(buf + occ_len, conv_param, buf_len - occ_len);
		mfree(conv_param);
		occ_len+=l;
		buf[occ_len++]='"';
		attr = attr->next;
	}

	if (node->subnode) {
		CHK(buf, 1);
		buf[occ_len++] = '>';

		sn = node->subnode;
		while (sn) {
			sub_buf = XML_Get_Node_As_Text(sn);
			if (sub_buf) {
				l = strlen(sub_buf);
				CHK(buf, l);
				strncpy(buf + occ_len, sub_buf, buf_len - occ_len);
				occ_len+=l;
				mfree(sub_buf);
			}
			sn = sn->next;
		}
		/* Closing tag */
		l = strlen(node->name);
		CHK(buf, l+3);
		buf[occ_len++] = '<';
		buf[occ_len++] = '/';
		strncpy(buf + occ_len, node->name, buf_len - occ_len);
		occ_len+=l;
		buf[occ_len++] = '>';
	} else {
		if (node->value) {
			CHK(buf, 1);
			buf[occ_len++] = '>';
			conv_param = Mask_Special_Syms(node->value);
			l = strlen(conv_param);
			CHK(buf, l);
//			occ_len++;
			strncpy(buf + occ_len, conv_param, buf_len - occ_len);
			occ_len+=l;
			mfree(conv_param);
                        /* Closing tag */
			l = strlen(node->name);
			CHK(buf, l+3);
			buf[occ_len++] = '<';
			buf[occ_len++] = '/';
			strncpy(buf + occ_len, node->name, buf_len - occ_len);
			occ_len+=l;
			buf[occ_len++] = '>';
		} else {
			CHK(buf, 2);
			buf[occ_len++] = '/';
			buf[occ_len] = '>';
		}
	}
//	printf("XML node name %s has dump\n%s\n", node->name, buf);
	return (buf);
}
/*
 * Local Variables: *
 * c-file-style: "bsd" *
 * End: *
 */
