Import dEQP.
[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                 default:        return DE_NULL;
45         }
46 }
47
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
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
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
103 Writer::~Writer (void)
104 {
105 }
106
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
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
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