blob: feaa2c97a8c1f5b8057352421153b3a06d374cf6 [file] [log] [blame]
Jarkko Poyry3c827362014-09-02 11:48:52 +03001/*-------------------------------------------------------------------------
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
28namespace xe
29{
30namespace xml
31{
32
33const Writer::EndElementType Writer::EndElement = Writer::EndElementType();
34
35inline const char* getEscapeEntity (char ch)
36{
37 switch (ch)
38 {
39 case '<': return "&lt;";
40 case '>': return "&gt;";
41 case '&': return "&amp;";
42 case '\'': return "&apos;";
43 case '"': return "&quot;";
Jarkko Pöyry368115f2015-03-25 11:26:54 -070044
45 // Non-printable characters.
46 case 0: return "&lt;NUL&gt;";
47 case 1: return "&lt;SOH&gt;";
48 case 2: return "&lt;STX&gt;";
49 case 3: return "&lt;ETX&gt;";
50 case 4: return "&lt;EOT&gt;";
51 case 5: return "&lt;ENQ&gt;";
52 case 6: return "&lt;ACK&gt;";
53 case 7: return "&lt;BEL&gt;";
54 case 8: return "&lt;BS&gt;";
55 case 11: return "&lt;VT&gt;";
56 case 12: return "&lt;FF&gt;";
57 case 14: return "&lt;SO&gt;";
58 case 15: return "&lt;SI&gt;";
59 case 16: return "&lt;DLE&gt;";
60 case 17: return "&lt;DC1&gt;";
61 case 18: return "&lt;DC2&gt;";
62 case 19: return "&lt;DC3&gt;";
63 case 20: return "&lt;DC4&gt;";
64 case 21: return "&lt;NAK&gt;";
65 case 22: return "&lt;SYN&gt;";
66 case 23: return "&lt;ETB&gt;";
67 case 24: return "&lt;CAN&gt;";
68 case 25: return "&lt;EM&gt;";
69 case 26: return "&lt;SUB&gt;";
70 case 27: return "&lt;ESC&gt;";
71 case 28: return "&lt;FS&gt;";
72 case 29: return "&lt;GS&gt;";
73 case 30: return "&lt;RS&gt;";
74 case 31: return "&lt;US&gt;";
75
Jarkko Poyry3c827362014-09-02 11:48:52 +030076 default: return DE_NULL;
77 }
78}
79
80std::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
115int 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
127Writer::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
135Writer::~Writer (void)
136{
137}
138
139Writer& 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
159Writer& 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
169Writer& 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