| /*------------------------------------------------------------------------- |
| * 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 nullptr; |
| } |
| } |
| |
| 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 |