/*------------------------------------------------------------------------- * 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 "<"; case '>': return ">"; case '&': return "&"; case '\'': return "'"; case '"': return """; // Non-printable characters. case 0: return "<NUL>"; case 1: return "<SOH>"; case 2: return "<STX>"; case 3: return "<ETX>"; case 4: return "<EOT>"; case 5: return "<ENQ>"; case 6: return "<ACK>"; case 7: return "<BEL>"; case 8: return "<BS>"; case 11: return "<VT>"; case 12: return "<FF>"; case 14: return "<SO>"; case 15: return "<SI>"; case 16: return "<DLE>"; case 17: return "<DC1>"; case 18: return "<DC2>"; case 19: return "<DC3>"; case 20: return "<DC4>"; case 21: return "<NAK>"; case 22: return "<SYN>"; case 23: return "<ETB>"; case 24: return "<CAN>"; case 25: return "<EM>"; case 26: return "<SUB>"; case 27: return "<ESC>"; case 28: return "<FS>"; case 29: return "<GS>"; case 30: return "<RS>"; case 31: return "<US>"; 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)(deUint8)(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; } } // xml } // xe