blob: b22a0d2326f9774b615cad5107fa99bdcbb84563 [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program Test Executor
* ------------------------------------------
*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief XML Writer.
*//*--------------------------------------------------------------------*/
#include "xeXMLWriter.hpp"
#include <cstring>
namespace xe
{
namespace xml
{
const Writer::EndElementType Writer::EndElement = Writer::EndElementType();
inline const char *getEscapeEntity(char ch)
{
switch (ch)
{
case '<':
return "&lt;";
case '>':
return "&gt;";
case '&':
return "&amp;";
case '\'':
return "&apos;";
case '"':
return "&quot;";
// Non-printable characters.
case 0:
return "&lt;NUL&gt;";
case 1:
return "&lt;SOH&gt;";
case 2:
return "&lt;STX&gt;";
case 3:
return "&lt;ETX&gt;";
case 4:
return "&lt;EOT&gt;";
case 5:
return "&lt;ENQ&gt;";
case 6:
return "&lt;ACK&gt;";
case 7:
return "&lt;BEL&gt;";
case 8:
return "&lt;BS&gt;";
case 11:
return "&lt;VT&gt;";
case 12:
return "&lt;FF&gt;";
case 14:
return "&lt;SO&gt;";
case 15:
return "&lt;SI&gt;";
case 16:
return "&lt;DLE&gt;";
case 17:
return "&lt;DC1&gt;";
case 18:
return "&lt;DC2&gt;";
case 19:
return "&lt;DC3&gt;";
case 20:
return "&lt;DC4&gt;";
case 21:
return "&lt;NAK&gt;";
case 22:
return "&lt;SYN&gt;";
case 23:
return "&lt;ETB&gt;";
case 24:
return "&lt;CAN&gt;";
case 25:
return "&lt;EM&gt;";
case 26:
return "&lt;SUB&gt;";
case 27:
return "&lt;ESC&gt;";
case 28:
return "&lt;FS&gt;";
case 29:
return "&lt;GS&gt;";
case 30:
return "&lt;RS&gt;";
case 31:
return "&lt;US&gt;";
default:
return DE_NULL;
}
}
std::streamsize EscapeStreambuf::xsputn(const char *s, std::streamsize count)
{
std::streamsize numWritten = 0;
for (std::streamsize inPos = 0; inPos < count; inPos++)
{
const char *entity = getEscapeEntity(s[inPos]);
if (entity)
{
// Flush data prior to entity.
if (inPos > numWritten)
{
m_dst.write(s + numWritten, inPos - numWritten);
if (m_dst.fail())
return numWritten;
}
// Flush entity value
m_dst.write(entity, (std::streamsize)strlen(entity));
numWritten = inPos + 1;
}
}
if (numWritten < count)
{
m_dst.write(s + numWritten, count - numWritten);
if (m_dst.fail())
return numWritten;
}
return count;
}
int EscapeStreambuf::overflow(int ch)
{
if (ch == -1)
return -1;
else
{
DE_ASSERT((ch & 0xff) == ch);
const char chVal = (char)(uint8_t)(ch & 0xff);
return xsputn(&chVal, 1) == 1 ? ch : -1;
}
}
Writer::Writer(std::ostream &dst) : m_rawDst(dst), m_dataBuf(dst), m_dataStr(&m_dataBuf), m_state(STATE_DATA)
{
}
Writer::~Writer(void)
{
}
Writer &Writer::operator<<(const BeginElement &begin)
{
if (m_state == STATE_ELEMENT)
m_rawDst << ">";
if (m_state == STATE_ELEMENT || m_state == STATE_ELEMENT_END)
{
m_rawDst << "\n";
for (int i = 0; i < (int)m_elementStack.size(); i++)
m_rawDst << " ";
}
m_rawDst << "<" << begin.element;
m_elementStack.push_back(begin.element);
m_state = STATE_ELEMENT;
return *this;
}
Writer &Writer::operator<<(const Attribute &attribute)
{
DE_ASSERT(m_state == STATE_ELEMENT);
// \todo [2012-09-05 pyry] Escape?
m_rawDst << " " << attribute.name << "=\"" << attribute.value << "\"";
return *this;
}
Writer &Writer::operator<<(const EndElementType &)
{
if (m_state == STATE_ELEMENT)
m_rawDst << "/>";
else
{
if (m_state == STATE_ELEMENT_END)
{
m_rawDst << "\n";
for (int i = 0; i < (int)m_elementStack.size() - 1; i++)
m_rawDst << " ";
}
m_rawDst << "</" << m_elementStack.back() << ">";
}
m_elementStack.pop_back();
m_state = STATE_ELEMENT_END;
return *this;
}
} // namespace xml
} // namespace xe