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
getEscapeEntity(char ch)35 inline const char *getEscapeEntity(char ch)
36 {
37 switch (ch)
38 {
39 case '<':
40 return "<";
41 case '>':
42 return ">";
43 case '&':
44 return "&";
45 case '\'':
46 return "'";
47 case '"':
48 return """;
49
50 // Non-printable characters.
51 case 0:
52 return "<NUL>";
53 case 1:
54 return "<SOH>";
55 case 2:
56 return "<STX>";
57 case 3:
58 return "<ETX>";
59 case 4:
60 return "<EOT>";
61 case 5:
62 return "<ENQ>";
63 case 6:
64 return "<ACK>";
65 case 7:
66 return "<BEL>";
67 case 8:
68 return "<BS>";
69 case 11:
70 return "<VT>";
71 case 12:
72 return "<FF>";
73 case 14:
74 return "<SO>";
75 case 15:
76 return "<SI>";
77 case 16:
78 return "<DLE>";
79 case 17:
80 return "<DC1>";
81 case 18:
82 return "<DC2>";
83 case 19:
84 return "<DC3>";
85 case 20:
86 return "<DC4>";
87 case 21:
88 return "<NAK>";
89 case 22:
90 return "<SYN>";
91 case 23:
92 return "<ETB>";
93 case 24:
94 return "<CAN>";
95 case 25:
96 return "<EM>";
97 case 26:
98 return "<SUB>";
99 case 27:
100 return "<ESC>";
101 case 28:
102 return "<FS>";
103 case 29:
104 return "<GS>";
105 case 30:
106 return "<RS>";
107 case 31:
108 return "<US>";
109
110 default:
111 return DE_NULL;
112 }
113 }
114
xsputn(const char * s,std::streamsize count)115 std::streamsize EscapeStreambuf::xsputn(const char *s, std::streamsize count)
116 {
117 std::streamsize numWritten = 0;
118
119 for (std::streamsize inPos = 0; inPos < count; inPos++)
120 {
121 const char *entity = getEscapeEntity(s[inPos]);
122
123 if (entity)
124 {
125 // Flush data prior to entity.
126 if (inPos > numWritten)
127 {
128 m_dst.write(s + numWritten, inPos - numWritten);
129 if (m_dst.fail())
130 return numWritten;
131 }
132
133 // Flush entity value
134 m_dst.write(entity, (std::streamsize)strlen(entity));
135
136 numWritten = inPos + 1;
137 }
138 }
139
140 if (numWritten < count)
141 {
142 m_dst.write(s + numWritten, count - numWritten);
143 if (m_dst.fail())
144 return numWritten;
145 }
146
147 return count;
148 }
149
overflow(int ch)150 int EscapeStreambuf::overflow(int ch)
151 {
152 if (ch == -1)
153 return -1;
154 else
155 {
156 DE_ASSERT((ch & 0xff) == ch);
157 const char chVal = (char)(uint8_t)(ch & 0xff);
158 return xsputn(&chVal, 1) == 1 ? ch : -1;
159 }
160 }
161
Writer(std::ostream & dst)162 Writer::Writer(std::ostream &dst) : m_rawDst(dst), m_dataBuf(dst), m_dataStr(&m_dataBuf), m_state(STATE_DATA)
163 {
164 }
165
~Writer(void)166 Writer::~Writer(void)
167 {
168 }
169
operator <<(const BeginElement & begin)170 Writer &Writer::operator<<(const BeginElement &begin)
171 {
172 if (m_state == STATE_ELEMENT)
173 m_rawDst << ">";
174
175 if (m_state == STATE_ELEMENT || m_state == STATE_ELEMENT_END)
176 {
177 m_rawDst << "\n";
178 for (int i = 0; i < (int)m_elementStack.size(); i++)
179 m_rawDst << " ";
180 }
181
182 m_rawDst << "<" << begin.element;
183
184 m_elementStack.push_back(begin.element);
185 m_state = STATE_ELEMENT;
186
187 return *this;
188 }
189
operator <<(const Attribute & attribute)190 Writer &Writer::operator<<(const Attribute &attribute)
191 {
192 DE_ASSERT(m_state == STATE_ELEMENT);
193
194 // \todo [2012-09-05 pyry] Escape?
195 m_rawDst << " " << attribute.name << "=\"" << attribute.value << "\"";
196
197 return *this;
198 }
199
operator <<(const EndElementType &)200 Writer &Writer::operator<<(const EndElementType &)
201 {
202 if (m_state == STATE_ELEMENT)
203 m_rawDst << "/>";
204 else
205 {
206 if (m_state == STATE_ELEMENT_END)
207 {
208 m_rawDst << "\n";
209 for (int i = 0; i < (int)m_elementStack.size() - 1; i++)
210 m_rawDst << " ";
211 }
212
213 m_rawDst << "</" << m_elementStack.back() << ">";
214 }
215
216 m_elementStack.pop_back();
217 m_state = STATE_ELEMENT_END;
218
219 return *this;
220 }
221
222 } // namespace xml
223 } // namespace xe
224