1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program Test Executor 3 * ------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief XML Writer. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "xeXMLWriter.hpp" 25 26 #include <cstring> 27 28 namespace xe 29 { 30 namespace xml 31 { 32 33 const Writer::EndElementType Writer::EndElement = Writer::EndElementType(); 34 35 inline const char* getEscapeEntity (char ch) 36 { 37 switch (ch) 38 { 39 case '<': return "<"; 40 case '>': return ">"; 41 case '&': return "&"; 42 case '\'': return "'"; 43 case '"': return """; 44 45 // Non-printable characters. 46 case 0: return "<NUL>"; 47 case 1: return "<SOH>"; 48 case 2: return "<STX>"; 49 case 3: return "<ETX>"; 50 case 4: return "<EOT>"; 51 case 5: return "<ENQ>"; 52 case 6: return "<ACK>"; 53 case 7: return "<BEL>"; 54 case 8: return "<BS>"; 55 case 11: return "<VT>"; 56 case 12: return "<FF>"; 57 case 14: return "<SO>"; 58 case 15: return "<SI>"; 59 case 16: return "<DLE>"; 60 case 17: return "<DC1>"; 61 case 18: return "<DC2>"; 62 case 19: return "<DC3>"; 63 case 20: return "<DC4>"; 64 case 21: return "<NAK>"; 65 case 22: return "<SYN>"; 66 case 23: return "<ETB>"; 67 case 24: return "<CAN>"; 68 case 25: return "<EM>"; 69 case 26: return "<SUB>"; 70 case 27: return "<ESC>"; 71 case 28: return "<FS>"; 72 case 29: return "<GS>"; 73 case 30: return "<RS>"; 74 case 31: return "<US>"; 75 76 default: return DE_NULL; 77 } 78 } 79 80 std::streamsize EscapeStreambuf::xsputn (const char* s, std::streamsize count) 81 { 82 std::streamsize numWritten = 0; 83 84 for (std::streamsize inPos = 0; inPos < count; inPos++) 85 { 86 const char* entity = getEscapeEntity(s[inPos]); 87 88 if (entity) 89 { 90 // Flush data prior to entity. 91 if (inPos > numWritten) 92 { 93 m_dst.write(s + numWritten, inPos-numWritten); 94 if (m_dst.fail()) 95 return numWritten; 96 } 97 98 // Flush entity value 99 m_dst.write(entity, (std::streamsize)strlen(entity)); 100 101 numWritten = inPos+1; 102 } 103 } 104 105 if (numWritten < count) 106 { 107 m_dst.write(s + numWritten, count-numWritten); 108 if (m_dst.fail()) 109 return numWritten; 110 } 111 112 return count; 113 } 114 115 int EscapeStreambuf::overflow (int ch) 116 { 117 if (ch == -1) 118 return -1; 119 else 120 { 121 DE_ASSERT((ch & 0xff) == ch); 122 const char chVal = (char)(deUint8)(ch & 0xff); 123 return xsputn(&chVal, 1) == 1 ? ch : -1; 124 } 125 } 126 127 Writer::Writer (std::ostream& dst) 128 : m_rawDst (dst) 129 , m_dataBuf (dst) 130 , m_dataStr (&m_dataBuf) 131 , m_state (STATE_DATA) 132 { 133 } 134 135 Writer::~Writer (void) 136 { 137 } 138 139 Writer& Writer::operator<< (const BeginElement& begin) 140 { 141 if (m_state == STATE_ELEMENT) 142 m_rawDst << ">"; 143 144 if (m_state == STATE_ELEMENT || m_state == STATE_ELEMENT_END) 145 { 146 m_rawDst << "\n"; 147 for (int i = 0; i < (int)m_elementStack.size(); i++) 148 m_rawDst << " "; 149 } 150 151 m_rawDst << "<" << begin.element; 152 153 m_elementStack.push_back(begin.element); 154 m_state = STATE_ELEMENT; 155 156 return *this; 157 } 158 159 Writer& Writer::operator<< (const Attribute& attribute) 160 { 161 DE_ASSERT(m_state == STATE_ELEMENT); 162 163 // \todo [2012-09-05 pyry] Escape? 164 m_rawDst << " " << attribute.name << "=\"" << attribute.value << "\""; 165 166 return *this; 167 } 168 169 Writer& Writer::operator<< (const EndElementType&) 170 { 171 if (m_state == STATE_ELEMENT) 172 m_rawDst << "/>"; 173 else 174 { 175 if (m_state == STATE_ELEMENT_END) 176 { 177 m_rawDst << "\n"; 178 for (int i = 0; i < (int)m_elementStack.size()-1; i++) 179 m_rawDst << " "; 180 } 181 182 m_rawDst << "</" << m_elementStack.back() << ">"; 183 } 184 185 m_elementStack.pop_back(); 186 m_state = STATE_ELEMENT_END; 187 188 return *this; 189 } 190 191 } // xml 192 } // xe 193