am 342b03b5: (-s ours) am ca04416b: am 33c9e110: am cee84aa0: am 652dd63a: Merge...
[platform/upstream/VK-GL-CTS.git] / executor / xeXMLWriter.cpp
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
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
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
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
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
135 Writer::~Writer (void)
136 {
137 }
138
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
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
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