static const char version[] = "$Id$";

/* 
 * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include <string.h>

#ifdef HAVE_LANGINFO_H
#   include <langinfo.h>
#endif

#include "domnode-xml.h"

/* Generated by bison(1) */
#include "domnode-xml-parser.h"

/* Generated by flex(1) */
#define YY_HEADER_NO_UNDEFS 1
#include "domnode-xml-scanner.h"

extern int __sd_domnode_xml_parse(struct __sd_domnode_xml_maker*);

/******************************************************************************/
static int xml_fwrite(const sd_domnode_t* this, FILE* a_stream, int a_indent)
{
    sd_list_iter_t* iter;
    int i;
    
    if (!this || !this->name || !a_stream)
	return -1;
    
    for (i = 0; i < a_indent; i++)
	fprintf(a_stream, "    ");
    
    if (this->name && strcmp(this->name, "#comment") == 0) {
	fprintf(a_stream, "<!-- %s -->\n", this->value);
	return 0;
    } 
    
    fprintf(a_stream, "<%s", this->name);

    for (iter = sd_list_begin(this->attrs); iter != sd_list_end(this->attrs);
	 iter = sd_list_iter_next(iter)) {
	sd_domnode_t* node = iter->data;
	
	fprintf(a_stream, " %s=\"%s\"", node->name, node->value);
    }
    
    if (this->value || sd_list_get_nelem(this->children)) {
	fprintf(a_stream, ">\n");
	
	if (this->value) {
	    for (i = 0; i < a_indent + 1; i++)
		fprintf(a_stream, "    ");
	    fprintf(a_stream, "%s\n", this->value);
	}
    
	for (iter = sd_list_begin(this->children);
	     iter != sd_list_end(this->children);
	     iter = sd_list_iter_next(iter)) {
	    sd_domnode_t* node = iter->data;
	    
	    if (xml_fwrite(node, a_stream, a_indent + 1) == -1)
		return -1;
	}
	
	for (i = 0; i < a_indent; i++)
	    fprintf(a_stream, "    ");	
	fprintf(a_stream, "</%s>\n", this->name);
    } else {
	fprintf(a_stream, "/>\n");
    }
    
    return 0;
}

/******************************************************************************/
extern int __sd_domnode_xml_write(const sd_domnode_t* this, char** a_buffer,
				  size_t* a_size)
{
    /* TODO: to be implemented */
    return -1;
}

/******************************************************************************/
extern int __sd_domnode_xml_fwrite(const sd_domnode_t* this, FILE* a_stream)
{
#ifdef HAVE_NL_LANGINFO
    fprintf(a_stream, "<?xml version=\"1.0\" encoding=\"%s\"?>\n\n",
	    nl_langinfo(CODESET));
#else
    fprintf(a_stream, "<?xml version=\"1.0\"?>\n\n");
#endif
    
    return xml_fwrite(this, a_stream, 0);
}

/******************************************************************************/
static int xml_parse(sd_domnode_t** a_node, yyscan_t a_scanner)
{
    int r;
    struct __sd_domnode_xml_maker maker;
    
    maker.scanner	= a_scanner;
    maker.elements	= sd_stack_new(0);
    maker.root		= 0;
    
    if (! (r = __sd_domnode_xml_parse(&maker))) *a_node = maker.root;
    
    sd_stack_delete(maker.elements, 0);
    
    return r;
}

/******************************************************************************/
extern int __sd_domnode_xml_fread(sd_domnode_t** a_node, FILE* a_stream)
{
    int r;
    yyscan_t scanner;
    
    yylex_init(&scanner);
    yyset_in(a_stream, scanner);
    
    r = xml_parse(a_node, scanner);
    
    yylex_destroy(scanner);
    
    return r;
}

/******************************************************************************/
extern int __sd_domnode_xml_read(sd_domnode_t** a_node, const char* a_buffer,
				 size_t a_size)
{
    int r;
    yyscan_t scanner;
    
    yylex_init(&scanner);
    yy_switch_to_buffer(yy_scan_bytes(a_buffer, a_size, scanner), scanner);
    
    r = xml_parse(a_node, scanner);
    
    yylex_destroy(scanner);
    
    return r;
}
