| /*------------------------------------------------------------------------- | |
| * 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 |