#include <stdio.h>		//fileno

#include "IoXmlWriter.h"
#include "IoState.h"
#include "IoNumber.h"
#include "IoList.h"
#include "IoMap.h"
#include "IoFile.h"

#define DATA(self) ((IoXmlWriterData*)IoObject_dataPointer(self))

IoTag *IoXmlWriter_tag(void *state)
{
	IoTag *tag = IoTag_newWithName_("XmlWriter");
	tag->state = state;
	tag->cloneFunc = (TagCloneFunc *)IoXmlWriter_rawClone;
	tag->freeFunc = (TagFreeFunc *)IoXmlWriter_free;
	tag->markFunc = (TagMarkFunc *)IoXmlWriter_mark;
	return tag;
}

IoXmlWriter *IoXmlWriter_rawClone(IoXmlWriter *proto)
{
	IoObject *self = IoObject_rawClonePrimitive(proto);
	IoObject_setDataPointer_(self, cpalloc(IoObject_dataPointer(proto), sizeof(IoXmlWriterData)));
	return self;
}

IoXmlWriter *IoXmlWriter_proto(void *state)
{
	IoObject *self = IoObject_new(state);
	self->tag = IoXmlWriter_tag(state);
	
	IoObject_setDataPointer_(self, calloc(1, sizeof(IoXmlWriterData)));
	
	IoState_registerProtoWithFunc_(state, self, IoXmlWriter_proto);
	IoMethodTable methodTable[] = {
                {"openFilename", IoXmlWriter_openFilename},
                {"close", IoXmlWriter_close},
                {"flush", IoXmlWriter_flush},

                {"setIndent", IoXmlWriter_setIndent},
                {"setIndentString", IoXmlWriter_setIndentString},

                {"startDocument", IoXmlWriter_startDocument},
                {"endDocument", IoXmlWriter_endDocument},

                {"startComment", IoXmlWriter_startComment},
                {"endComment", IoXmlWriter_endComment},
                {"writeComment", IoXmlWriter_writeComment},

                {"startElement", IoXmlWriter_startElement},
                {"startElementNS", IoXmlWriter_startElementNS},
                {"endElement", IoXmlWriter_endElement},
                {"fullEndElement", IoXmlWriter_fullEndElement},

                {"writeElement", IoXmlWriter_writeElement},
                {"writeElementNS", IoXmlWriter_writeElementNS},

                {"writeRaw", IoXmlWriter_writeRaw},
                {"writeString", IoXmlWriter_writeString},
                {"writeBase64", IoXmlWriter_writeBase64},
                {"writeBinHex", IoXmlWriter_writeBinHex},

                {"startAttribute", IoXmlWriter_startAttribute},
                {"startAttributeNS", IoXmlWriter_startAttributeNS},
                {"endAttribute", IoXmlWriter_endAttribute},

                {"writeAttribute", IoXmlWriter_writeAttribute},
                {"writeAttributeNS", IoXmlWriter_writeAttributeNS},

                {"startPI", IoXmlWriter_startPI},
                {"endPI", IoXmlWriter_endPI},
                {"writePI", IoXmlWriter_writePI},

                {"startCDATA", IoXmlWriter_startCDATA},
                {"endCDATA", IoXmlWriter_endCDATA},
                {"writeCDATA", IoXmlWriter_writeCDATA},

                {"startDTD", IoXmlWriter_startDTD},
                {"endDTD", IoXmlWriter_endDTD},
                {"writeDTD", IoXmlWriter_writeDTD},

                {"startDTDElement", IoXmlWriter_startDTDElement},
                {"endDTDElement", IoXmlWriter_endDTDElement},
                {"writeDTDElement", IoXmlWriter_writeDTDElement},
                
                {"startDTDAttlist", IoXmlWriter_startDTDAttlist},
                {"endDTDAttlist", IoXmlWriter_endDTDAttlist},
                {"writeDTDAttlist", IoXmlWriter_writeDTDAttlist},
               
                {"writeStartDTDEntity", IoXmlWriter_writeStartDTDEntity},
                {"writeEndDTDEntity", IoXmlWriter_writeEndDTDEntity},
                {"writeDTDInternalEntity", IoXmlWriter_writeDTDInternalEntity},
                {"writeDTDExternalEntity", IoXmlWriter_writeDTDExternalEntity},
                {"writeDTDExternalEntityContents", IoXmlWriter_writeDTDExternalEntityContents},
                {"writeDTDEntity", IoXmlWriter_writeDTDEntity},
                {"writeDTDNotation", IoXmlWriter_writeDTDNotation},

		{NULL, NULL}
	};
	IoObject_addMethodTable_(self, methodTable);
	return self;
}

IoXmlWriter *IoXmlWriter_new(void *state)
{
        IoXmlWriter *proto = IoState_protoWithInitFunction_(state, IoXmlWriter_proto);
	return IOCLONE(proto);
}

void IoXmlWriter_free(IoXmlWriter *self)
{
	if (DATA(self)->writer) 
        {
                // TODO: handle error
                int rc = xmlTextWriterEndDocument(DATA(self)->writer);
		xmlFreeTextWriter(DATA(self)->writer);
        }
	free(IoObject_dataPointer(self));
}

void IoXmlWriter_mark(IoXmlWriter *self)
{
}

/* ------------------------------------------------------------- */

char *IoMessage_locals_cStringArgAtOrNULL_(IoMessage *self, IoObject *locals, int n)
{
        IoObject *value = IoMessage_locals_valueArgAt_(self, locals, n);
        if (value == IOSTATE->ioNil)
        {
                return NULL;
        }
	if (!ISSEQ(value))
	{
		IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
	}
        return CSTRING(value);
}

char *IoMessage_locals_cStringArgAtOrNULLSize_(IoMessage *self, IoObject *locals, int n, int *size)
{
        IoObject *value = IoMessage_locals_valueArgAt_(self, locals, n);
        if (value == IOSTATE->ioNil)
        {
                *size = 0;
                return NULL;
        }
	if (!ISSEQ(value))
	{
		IoMessage_locals_numberArgAt_errorForType_(self, locals, n, "Sequence");
	}
        *size = IOSEQ_LENGTH(value);
        return CSTRING(value);
}

/* ------------------------------------------------------------- */

IoObject *IoXmlWriter_openFilename(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	IoSymbol *path = IoMessage_locals_symbolArgAt_(m, locals, 0);
        DATA(self)->writer = xmlNewTextWriterFilename(CSTRING(path), 0);
        return self;
}

IoObject *IoXmlWriter_startDocument(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *version = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *encoding = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *standalone = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartDocument(DATA(self)->writer, version, encoding, standalone);

        return self;
}

IoObject *IoXmlWriter_endDocument(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndDocument(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_close(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        xmlFreeTextWriter(DATA(self)->writer);
        DATA(self)->writer = NULL;
        return self;
}
                
IoObject *IoXmlWriter_startComment(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartComment(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_endComment(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndComment(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeComment(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *comment = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteComment(DATA(self)->writer, comment);

        return self;
}

IoObject *IoXmlWriter_startElement(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartElement(DATA(self)->writer, name);

        return self;
}

IoObject *IoXmlWriter_startElementNS(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *prefix = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *namespaceURI = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartElementNS(DATA(self)->writer, prefix, name, namespaceURI);

        return self;
}

IoObject *IoXmlWriter_endElement(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndElement(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_fullEndElement(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterFullEndElement(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeElement(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteElement(DATA(self)->writer, name, content);

        return self;
}

IoObject *IoXmlWriter_writeElementNS(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *prefix = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *namespaceURI = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 3);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteElementNS(DATA(self)->writer, prefix, name, namespaceURI, content);

        return self;
}

IoObject *IoXmlWriter_writeRaw(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteRaw(DATA(self)->writer, content);

        return self;
}

IoObject *IoXmlWriter_writeString(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteString(DATA(self)->writer, content);

        return self;
}

IoObject *IoXmlWriter_writeBase64(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        const int start = 0;
        int len = 0;
	const char *content = IoMessage_locals_cStringArgAtOrNULLSize_(m, locals, 0, &len);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteBase64(DATA(self)->writer, content, start, len);

        return self;
}

IoObject *IoXmlWriter_writeBinHex(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        const int start = 0;
        int len = 0;
	const char *content = IoMessage_locals_cStringArgAtOrNULLSize_(m, locals, 0, &len);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteBinHex(DATA(self)->writer, content, start, len);

        return self;
}

IoObject *IoXmlWriter_startAttribute(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartAttribute(DATA(self)->writer, name);

        return self;
}

IoObject *IoXmlWriter_startAttributeNS(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *prefix = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *namespaceURI = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartAttributeNS(DATA(self)->writer, prefix, name, namespaceURI);

        return self;
}

IoObject *IoXmlWriter_endAttribute(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndAttribute(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeAttribute(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteAttribute(DATA(self)->writer, name, content);

        return self;
}

IoObject *IoXmlWriter_writeAttributeNS(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *prefix = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *namespaceURI = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 3);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteAttributeNS(DATA(self)->writer, prefix, name, namespaceURI, content);

        return self;
}

IoObject *IoXmlWriter_startPI(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *target = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartPI(DATA(self)->writer, target);

        return self;
}

IoObject *IoXmlWriter_endPI(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndPI(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writePI(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *target = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWritePI(DATA(self)->writer, target, content);

        return self;
}

IoObject *IoXmlWriter_startCDATA(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartCDATA(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_endCDATA(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndCDATA(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeCDATA(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteCDATA(DATA(self)->writer, content);

        return self;
}

IoObject *IoXmlWriter_startDTD(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *pubid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *sysid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartDTD(DATA(self)->writer, name, pubid, sysid);

        return self;
}

IoObject *IoXmlWriter_endDTD(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndDTD(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeDTD(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *pubid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *sysid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);
	const char *subset = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 3);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTD(DATA(self)->writer, name, pubid, sysid, subset);

        return self;
}

IoObject *IoXmlWriter_startDTDElement(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartDTDElement(DATA(self)->writer, name);

        return self;
}

IoObject *IoXmlWriter_endDTDElement(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndDTDElement(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeDTDElement(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTDElement(DATA(self)->writer, name, content);

        return self;
}

IoObject *IoXmlWriter_startDTDAttlist(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartDTDAttlist(DATA(self)->writer, name);

        return self;
}

IoObject *IoXmlWriter_endDTDAttlist(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndDTDAttlist(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeDTDAttlist(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTDAttlist(DATA(self)->writer, name, content);

        return self;
}

IoObject *IoXmlWriter_writeStartDTDEntity(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	IoObject *peObj = IoMessage_locals_valueArgAt_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);

        IOASSERT(ISBOOL(peObj), "First argument must be true, false or nil.");

        const int pe = ISTRUE(peObj);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterStartDTDEntity(DATA(self)->writer, pe, name);

        return self;
}

IoObject *IoXmlWriter_writeEndDTDEntity(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterEndDTDEntity(DATA(self)->writer);

        return self;
}

IoObject *IoXmlWriter_writeDTDInternalEntity(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	IoObject *peObj = IoMessage_locals_valueArgAt_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);

        IOASSERT(ISBOOL(peObj), "First argument must be true, false or nil.");

        const int pe = ISTRUE(peObj);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTDInternalEntity(DATA(self)->writer, pe, name, content);

        return self;
}

IoObject *IoXmlWriter_writeDTDExternalEntity(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	IoObject *peObj = IoMessage_locals_valueArgAt_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *pubid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);
	const char *sysid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 3);
	const char *ndataid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 4);

        IOASSERT(ISBOOL(peObj), "First argument must be true, false or nil.");

        const int pe = ISTRUE(peObj);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTDExternalEntity(DATA(self)->writer, pe, name, pubid, sysid, ndataid);

        return self;
}

IoObject *IoXmlWriter_writeDTDExternalEntityContents(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *pubid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *sysid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *ndataid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTDExternalEntityContents(DATA(self)->writer, pubid, sysid, ndataid);

        return self;
}

IoObject *IoXmlWriter_writeDTDEntity(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	IoObject *peObj = IoMessage_locals_valueArgAt_(m, locals, 0);
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *pubid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);
	const char *sysid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 3);
	const char *ndataid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 4);
	const char *content = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 5);

        IOASSERT(ISBOOL(peObj), "First argument must be true, false or nil.");

        const int pe = ISTRUE(peObj);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTDEntity(DATA(self)->writer, pe, name, pubid, sysid, ndataid, content);

        return self;
}

IoObject *IoXmlWriter_writeDTDNotation(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *name = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);
	const char *pubid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 1);
	const char *sysid = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 2);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterWriteDTDNotation(DATA(self)->writer, name, pubid, sysid);

        return self;
}

IoObject *IoXmlWriter_setIndent(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	IoObject *indentObj = IoMessage_locals_valueArgAt_(m, locals, 0);

        IOASSERT(ISBOOL(indentObj), "First argument must be true, false or nil.");

        const int indent = ISTRUE(indentObj);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterSetIndent(DATA(self)->writer, indent);

        return self;
}

IoObject *IoXmlWriter_setIndentString(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
	const char *str = IoMessage_locals_cStringArgAtOrNULL_(m, locals, 0);

        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterSetIndentString(DATA(self)->writer, str);

        return self;
}

IoObject *IoXmlWriter_flush(IoXmlWriter *self, IoObject *locals, IoMessage *m)
{
        // TODO: require the writer to be open
        // TODO: detect hand handle error result
        int rc = xmlTextWriterFlush(DATA(self)->writer);

        return self;
}

