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