13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Helper Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief XML Writer.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "qpXmlWriter.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * qpXmlWriter stand-alone implementation.
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *----------------------------------------------------------------------*/
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemPool.h"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "dePoolArray.h"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct qpXmlWriter_s
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FILE*				outputFile;
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool				xmlPrevIsStartElement;
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool				xmlIsWriting;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					xmlElementDepth;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool writeEscaped (qpXmlWriter* writer, const char* str)
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char		buf[256 + 10];
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char*		d		= &buf[0];
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*	s		= str;
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool		isEOS	= DE_FALSE;
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	do
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Check for characters that need to be escaped. */
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char* repl = DE_NULL;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (*s)
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 0:		isEOS = DE_TRUE;		break;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case '<':	repl = "&lt;";			break;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case '>':	repl = "&gt;";			break;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case '&':	repl = "&amp;";			break;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case '\'':	repl = "&apos;";		break;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case '"':	repl = "&quot;";		break;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* Non-printable characters. */
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 1:		repl = "&lt;SOH&gt;";	break;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 2:		repl = "&lt;STX&gt;";	break;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 3:		repl = "&lt;ETX&gt;";	break;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 4:		repl = "&lt;EOT&gt;";	break;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 5:		repl = "&lt;ENQ&gt;";	break;
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 6:		repl = "&lt;ACK&gt;";	break;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 7:		repl = "&lt;BEL&gt;";	break;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 8:		repl = "&lt;BS&gt;";	break;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 11:	repl = "&lt;VT&gt;";	break;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 12:	repl = "&lt;FF&gt;";	break;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 14:	repl = "&lt;SO&gt;";	break;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 15:	repl = "&lt;SI&gt;";	break;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 16:	repl = "&lt;DLE&gt;";	break;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 17:	repl = "&lt;DC1&gt;";	break;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 18:	repl = "&lt;DC2&gt;";	break;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 19:	repl = "&lt;DC3&gt;";	break;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 20:	repl = "&lt;DC4&gt;";	break;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 21:	repl = "&lt;NAK&gt;";	break;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 22:	repl = "&lt;SYN&gt;";	break;
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 23:	repl = "&lt;ETB&gt;";	break;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 24:	repl = "&lt;CAN&gt;";	break;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 25:	repl = "&lt;EM&gt;";	break;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 26:	repl = "&lt;SUB&gt;";	break;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 27:	repl = "&lt;ESC&gt;";	break;
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 28:	repl = "&lt;FS&gt;";	break;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 29:	repl = "&lt;GS&gt;";	break;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 30:	repl = "&lt;RS&gt;";	break;
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case 31:	repl = "&lt;US&gt;";	break;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:	/* nada */				break;
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Write out char or escape sequence. */
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (repl)
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			s++;
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			strcpy(d, repl);
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			d += strlen(repl);
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			*d++ = *s++;
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Write buffer if EOS or buffer full. */
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isEOS || ((d - &buf[0]) >= 4))
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			*d = 0;
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fprintf(writer->outputFile, "%s", buf);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			d = &buf[0];
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} while (!isEOS);
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fflush(writer->outputFile);
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(d == &buf[0]); /* buffer must be empty */
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1223c827367444ee418f129b2c238299f49d3264554Jarkko PoyryqpXmlWriter* qpXmlWriter_createFileWriter (FILE* outputFile, deBool useCompression)
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpXmlWriter* writer = (qpXmlWriter*)deCalloc(sizeof(qpXmlWriter));
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!writer)
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(useCompression); /* no compression supported. */
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->outputFile = outputFile;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return writer;
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid qpXmlWriter_destroy (qpXmlWriter* writer)
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(writer);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(writer);
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool closePending (qpXmlWriter* writer)
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (writer->xmlPrevIsStartElement)
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, ">\n");
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writer->xmlPrevIsStartElement = DE_FALSE;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid qpXmlWriter_flush (qpXmlWriter* writer)
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	closePending(writer);
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool qpXmlWriter_startDocument (qpXmlWriter* writer)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(writer && !writer->xmlIsWriting);
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->xmlIsWriting			= DE_TRUE;
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->xmlElementDepth			= 0;
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->xmlPrevIsStartElement	= DE_FALSE;
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fprintf(writer->outputFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getIndentStr (int indentLevel)
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char	s_indentStr[33]	= "                                ";
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int	s_indentStrLen	= 32;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return &s_indentStr[s_indentStrLen - deMin32(s_indentStrLen, indentLevel)];
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool qpXmlWriter_endDocument (qpXmlWriter* writer)
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(writer);
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(writer->xmlIsWriting);
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(writer->xmlElementDepth == 0);
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	closePending(writer);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->xmlIsWriting = DE_FALSE;
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1853c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool qpXmlWriter_writeString (qpXmlWriter* writer, const char* str)
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (writer->xmlPrevIsStartElement)
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, ">");
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writer->xmlPrevIsStartElement = DE_FALSE;
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return writeEscaped(writer, str);
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1963c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool qpXmlWriter_startElement(qpXmlWriter* writer, const char* elementName, int numAttribs, const qpXmlAttribute* attribs)
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int ndx;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	closePending(writer);
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fprintf(writer->outputFile, "%s<%s", getIndentStr(writer->xmlElementDepth), elementName);
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (ndx = 0; ndx < numAttribs; ndx++)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const qpXmlAttribute* attrib = &attribs[ndx];
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, " %s=\"", attrib->name);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (attrib->type)
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case QP_XML_ATTRIBUTE_STRING:
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeEscaped(writer, attrib->stringValue);
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case QP_XML_ATTRIBUTE_INT:
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				char buf[64];
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				sprintf(buf, "%d", attrib->intValue);
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeEscaped(writer, buf);
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case QP_XML_ATTRIBUTE_BOOL:
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				writeEscaped(writer, attrib->boolValue ? "True" : "False");
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(DE_FALSE);
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, "\"");
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->xmlElementDepth++;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->xmlPrevIsStartElement = DE_TRUE;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool qpXmlWriter_endElement (qpXmlWriter* writer, const char* elementName)
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(writer && writer->xmlElementDepth > 0);
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	writer->xmlElementDepth--;
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (writer->xmlPrevIsStartElement) /* leave flag as-is */
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, " />\n");
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		writer->xmlPrevIsStartElement = DE_FALSE;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, "</%s>\n", /*getIndentStr(writer->xmlElementDepth),*/ elementName);
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool qpXmlWriter_writeBase64 (qpXmlWriter* writer, const deUint8* data, int numBytes)
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char s_base64Table[64] =
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		'A','B','C','D','E','F','G','H','I','J','K','L','M',
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		'a','b','c','d','e','f','g','h','i','j','k','l','m',
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		'n','o','p','q','r','s','t','u','v','w','x','y','z',
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		'0','1','2','3','4','5','6','7','8','9','+','/'
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numWritten	= 0;
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			srcNdx		= 0;
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool		writeIndent	= DE_TRUE;
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*	indentStr	= getIndentStr(writer->xmlElementDepth);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(writer && data && (numBytes > 0));
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Close and pending writes. */
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	closePending(writer);
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Loop all input chars. */
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (srcNdx < numBytes)
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int		numRead = deMin32(3, numBytes - srcNdx);
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8	s0 = data[srcNdx];
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8	s1 = (numRead >= 2) ? data[srcNdx+1] : 0;
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8	s2 = (numRead >= 3) ? data[srcNdx+2] : 0;
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		char	d[5];
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		srcNdx += numRead;
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		d[0] = s_base64Table[s0 >> 2];
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		d[1] = s_base64Table[((s0&0x3)<<4) | (s1>>4)];
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		d[2] = s_base64Table[((s1&0xF)<<2) | (s2>>6)];
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		d[3] = s_base64Table[s2&0x3F];
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		d[4] = 0;
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numRead < 3) d[3] = '=';
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numRead < 2) d[2] = '=';
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Write indent (if needed). */
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (writeIndent)
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fprintf(writer->outputFile, "%s", indentStr);
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeIndent = DE_FALSE;
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Write data. */
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, "%s", &d[0]);
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* EOL every now and then. */
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numWritten += 4;
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numWritten >= 64)
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fprintf(writer->outputFile, "\n");
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numWritten = 0;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			writeIndent = DE_TRUE;
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Last EOL. */
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numWritten > 0)
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fprintf(writer->outputFile, "\n");
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(srcNdx == numBytes);
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Common helper functions. */
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool qpXmlWriter_writeStringElement (qpXmlWriter* writer, const char* elementName, const char* elementContent)
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!qpXmlWriter_startElement(writer, elementName, 0, DE_NULL) ||
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		(elementContent && !qpXmlWriter_writeString(writer, elementContent)) ||
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		!qpXmlWriter_endElement(writer, elementName))
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
333