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 = "<"; break; 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case '>': repl = ">"; break; 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case '&': repl = "&"; break; 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case '\'': repl = "'"; break; 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case '"': repl = """; break; 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Non-printable characters. */ 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 1: repl = "<SOH>"; break; 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 2: repl = "<STX>"; break; 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 3: repl = "<ETX>"; break; 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 4: repl = "<EOT>"; break; 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 5: repl = "<ENQ>"; break; 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 6: repl = "<ACK>"; break; 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 7: repl = "<BEL>"; break; 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 8: repl = "<BS>"; break; 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 11: repl = "<VT>"; break; 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 12: repl = "<FF>"; break; 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 14: repl = "<SO>"; break; 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 15: repl = "<SI>"; break; 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 16: repl = "<DLE>"; break; 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 17: repl = "<DC1>"; break; 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 18: repl = "<DC2>"; break; 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 19: repl = "<DC3>"; break; 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 20: repl = "<DC4>"; break; 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 21: repl = "<NAK>"; break; 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 22: repl = "<SYN>"; break; 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 23: repl = "<ETB>"; break; 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 24: repl = "<CAN>"; break; 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 25: repl = "<EM>"; break; 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 26: repl = "<SUB>"; break; 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 27: repl = "<ESC>"; break; 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 28: repl = "<FS>"; break; 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 29: repl = "<GS>"; break; 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 30: repl = "<RS>"; break; 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case 31: repl = "<US>"; 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