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