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 '<':	return "&lt;";
40 		case '>':	return "&gt;";
41 		case '&':	return "&amp;";
42 		case '\'':	return "&apos;";
43 		case '"':	return "&quot;";
44 
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 
76 		default:	return DE_NULL;
77 	}
78 }
79 
xsputn(const char * s,std::streamsize count)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 
overflow(int ch)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 
Writer(std::ostream & dst)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 
~Writer(void)135 Writer::~Writer (void)
136 {
137 }
138 
operator <<(const BeginElement & begin)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 
operator <<(const Attribute & attribute)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 
operator <<(const EndElementType &)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