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 "<";
40 case '>': return ">";
41 case '&': return "&";
42 case '\'': return "'";
43 case '"': return """;
44 default: return DE_NULL;
45 }
46 }
47
xsputn(const char * s,std::streamsize count)48 std::streamsize EscapeStreambuf::xsputn (const char* s, std::streamsize count)
49 {
50 std::streamsize numWritten = 0;
51
52 for (std::streamsize inPos = 0; inPos < count; inPos++)
53 {
54 const char* entity = getEscapeEntity(s[inPos]);
55
56 if (entity)
57 {
58 // Flush data prior to entity.
59 if (inPos > numWritten)
60 {
61 m_dst.write(s + numWritten, inPos-numWritten);
62 if (m_dst.fail())
63 return numWritten;
64 }
65
66 // Flush entity value
67 m_dst.write(entity, (std::streamsize)strlen(entity));
68
69 numWritten = inPos+1;
70 }
71 }
72
73 if (numWritten < count)
74 {
75 m_dst.write(s + numWritten, count-numWritten);
76 if (m_dst.fail())
77 return numWritten;
78 }
79
80 return count;
81 }
82
overflow(int ch)83 int EscapeStreambuf::overflow (int ch)
84 {
85 if (ch == -1)
86 return -1;
87 else
88 {
89 DE_ASSERT((ch & 0xff) == ch);
90 const char chVal = (char)(deUint8)(ch & 0xff);
91 return xsputn(&chVal, 1) == 1 ? ch : -1;
92 }
93 }
94
Writer(std::ostream & dst)95 Writer::Writer (std::ostream& dst)
96 : m_rawDst (dst)
97 , m_dataBuf (dst)
98 , m_dataStr (&m_dataBuf)
99 , m_state (STATE_DATA)
100 {
101 }
102
~Writer(void)103 Writer::~Writer (void)
104 {
105 }
106
operator <<(const BeginElement & begin)107 Writer& Writer::operator<< (const BeginElement& begin)
108 {
109 if (m_state == STATE_ELEMENT)
110 m_rawDst << ">";
111
112 if (m_state == STATE_ELEMENT || m_state == STATE_ELEMENT_END)
113 {
114 m_rawDst << "\n";
115 for (int i = 0; i < (int)m_elementStack.size(); i++)
116 m_rawDst << " ";
117 }
118
119 m_rawDst << "<" << begin.element;
120
121 m_elementStack.push_back(begin.element);
122 m_state = STATE_ELEMENT;
123
124 return *this;
125 }
126
operator <<(const Attribute & attribute)127 Writer& Writer::operator<< (const Attribute& attribute)
128 {
129 DE_ASSERT(m_state == STATE_ELEMENT);
130
131 // \todo [2012-09-05 pyry] Escape?
132 m_rawDst << " " << attribute.name << "=\"" << attribute.value << "\"";
133
134 return *this;
135 }
136
operator <<(const EndElementType &)137 Writer& Writer::operator<< (const EndElementType&)
138 {
139 if (m_state == STATE_ELEMENT)
140 m_rawDst << "/>";
141 else
142 {
143 if (m_state == STATE_ELEMENT_END)
144 {
145 m_rawDst << "\n";
146 for (int i = 0; i < (int)m_elementStack.size()-1; i++)
147 m_rawDst << " ";
148 }
149
150 m_rawDst << "</" << m_elementStack.back() << ">";
151 }
152
153 m_elementStack.pop_back();
154 m_state = STATE_ELEMENT_END;
155
156 return *this;
157 }
158
159 } // xml
160 } // xe
161