xref: /aosp_15_r20/external/deqp/framework/xexml/xeXMLParser.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker #ifndef _XEXMLPARSER_HPP
2*35238bceSAndroid Build Coastguard Worker #define _XEXMLPARSER_HPP
3*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program Test Executor
5*35238bceSAndroid Build Coastguard Worker  * ------------------------------------------
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
8*35238bceSAndroid Build Coastguard Worker  *
9*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
10*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
11*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
14*35238bceSAndroid Build Coastguard Worker  *
15*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
16*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
17*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
19*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
20*35238bceSAndroid Build Coastguard Worker  *
21*35238bceSAndroid Build Coastguard Worker  *//*!
22*35238bceSAndroid Build Coastguard Worker  * \file
23*35238bceSAndroid Build Coastguard Worker  * \brief XML Parser.
24*35238bceSAndroid Build Coastguard Worker  *
25*35238bceSAndroid Build Coastguard Worker  * \todo [2012-06-07 pyry] Not supported / handled properly:
26*35238bceSAndroid Build Coastguard Worker  *  - xml namespaces (<ns:Element>)
27*35238bceSAndroid Build Coastguard Worker  *  - backslash escapes in strings
28*35238bceSAndroid Build Coastguard Worker  *  - &quot; -style escapes
29*35238bceSAndroid Build Coastguard Worker  *  - utf-8
30*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
31*35238bceSAndroid Build Coastguard Worker 
32*35238bceSAndroid Build Coastguard Worker #include "xeDefs.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "deRingBuffer.hpp"
34*35238bceSAndroid Build Coastguard Worker 
35*35238bceSAndroid Build Coastguard Worker #include <string>
36*35238bceSAndroid Build Coastguard Worker #include <map>
37*35238bceSAndroid Build Coastguard Worker 
38*35238bceSAndroid Build Coastguard Worker namespace xe
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker namespace xml
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker 
43*35238bceSAndroid Build Coastguard Worker enum Token
44*35238bceSAndroid Build Coastguard Worker {
45*35238bceSAndroid Build Coastguard Worker     TOKEN_INCOMPLETE = 0,               //!< Not enough data to determine token.
46*35238bceSAndroid Build Coastguard Worker     TOKEN_END_OF_STRING,                //!< End of document string.
47*35238bceSAndroid Build Coastguard Worker     TOKEN_DATA,                         //!< Block of data (anything outside tags).
48*35238bceSAndroid Build Coastguard Worker     TOKEN_COMMENT,                      //!< <!-- comment -->
49*35238bceSAndroid Build Coastguard Worker     TOKEN_IDENTIFIER,                   //!< Identifier (in tags).
50*35238bceSAndroid Build Coastguard Worker     TOKEN_STRING,                       //!< String (in tags).
51*35238bceSAndroid Build Coastguard Worker     TOKEN_TAG_START,                    //!< <
52*35238bceSAndroid Build Coastguard Worker     TOKEN_TAG_END,                      //!< >
53*35238bceSAndroid Build Coastguard Worker     TOKEN_END_TAG_START,                //!< </
54*35238bceSAndroid Build Coastguard Worker     TOKEN_EMPTY_ELEMENT_END,            //!< />
55*35238bceSAndroid Build Coastguard Worker     TOKEN_PROCESSING_INSTRUCTION_START, //!< <?
56*35238bceSAndroid Build Coastguard Worker     TOKEN_PROCESSING_INSTRUCTION_END,   //!< ?>
57*35238bceSAndroid Build Coastguard Worker     TOKEN_EQUAL,                        //!< =
58*35238bceSAndroid Build Coastguard Worker     TOKEN_ENTITY,                       //!< Entity reference, such as &amp;
59*35238bceSAndroid Build Coastguard Worker 
60*35238bceSAndroid Build Coastguard Worker     TOKEN_LAST
61*35238bceSAndroid Build Coastguard Worker };
62*35238bceSAndroid Build Coastguard Worker 
63*35238bceSAndroid Build Coastguard Worker enum Element
64*35238bceSAndroid Build Coastguard Worker {
65*35238bceSAndroid Build Coastguard Worker     ELEMENT_INCOMPLETE = 0, //!< Incomplete element.
66*35238bceSAndroid Build Coastguard Worker     ELEMENT_START,          //!< Element start.
67*35238bceSAndroid Build Coastguard Worker     ELEMENT_END,            //!< Element end.
68*35238bceSAndroid Build Coastguard Worker     ELEMENT_DATA,           //!< Data element.
69*35238bceSAndroid Build Coastguard Worker     ELEMENT_END_OF_STRING,  //!< End of document string.
70*35238bceSAndroid Build Coastguard Worker 
71*35238bceSAndroid Build Coastguard Worker     ELEMENT_LAST
72*35238bceSAndroid Build Coastguard Worker };
73*35238bceSAndroid Build Coastguard Worker 
74*35238bceSAndroid Build Coastguard Worker const char *getTokenName(Token token);
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker // \todo [2012-10-17 pyry] Add line number etc.
77*35238bceSAndroid Build Coastguard Worker class ParseError : public xe::ParseError
78*35238bceSAndroid Build Coastguard Worker {
79*35238bceSAndroid Build Coastguard Worker public:
ParseError(const std::string & message)80*35238bceSAndroid Build Coastguard Worker     ParseError(const std::string &message) : xe::ParseError(message)
81*35238bceSAndroid Build Coastguard Worker     {
82*35238bceSAndroid Build Coastguard Worker     }
83*35238bceSAndroid Build Coastguard Worker };
84*35238bceSAndroid Build Coastguard Worker 
85*35238bceSAndroid Build Coastguard Worker class Tokenizer
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker public:
88*35238bceSAndroid Build Coastguard Worker     Tokenizer(void);
89*35238bceSAndroid Build Coastguard Worker     ~Tokenizer(void);
90*35238bceSAndroid Build Coastguard Worker 
91*35238bceSAndroid Build Coastguard Worker     void clear(void); //!< Resets tokenizer to initial state.
92*35238bceSAndroid Build Coastguard Worker 
93*35238bceSAndroid Build Coastguard Worker     void feed(const uint8_t *bytes, int numBytes);
94*35238bceSAndroid Build Coastguard Worker     void advance(void);
95*35238bceSAndroid Build Coastguard Worker 
getToken(void) const96*35238bceSAndroid Build Coastguard Worker     Token getToken(void) const
97*35238bceSAndroid Build Coastguard Worker     {
98*35238bceSAndroid Build Coastguard Worker         return m_curToken;
99*35238bceSAndroid Build Coastguard Worker     }
getTokenLen(void) const100*35238bceSAndroid Build Coastguard Worker     int getTokenLen(void) const
101*35238bceSAndroid Build Coastguard Worker     {
102*35238bceSAndroid Build Coastguard Worker         return m_curTokenLen;
103*35238bceSAndroid Build Coastguard Worker     }
getTokenByte(int offset) const104*35238bceSAndroid Build Coastguard Worker     uint8_t getTokenByte(int offset) const
105*35238bceSAndroid Build Coastguard Worker     {
106*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_curToken != TOKEN_INCOMPLETE && m_curToken != TOKEN_END_OF_STRING);
107*35238bceSAndroid Build Coastguard Worker         return m_buf.peekBack(offset);
108*35238bceSAndroid Build Coastguard Worker     }
109*35238bceSAndroid Build Coastguard Worker     void getTokenStr(std::string &dst) const;
110*35238bceSAndroid Build Coastguard Worker     void appendTokenStr(std::string &dst) const;
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker     void getString(std::string &dst) const;
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker private:
115*35238bceSAndroid Build Coastguard Worker     Tokenizer(const Tokenizer &other);
116*35238bceSAndroid Build Coastguard Worker     Tokenizer &operator=(const Tokenizer &other);
117*35238bceSAndroid Build Coastguard Worker 
118*35238bceSAndroid Build Coastguard Worker     int getChar(int offset) const;
119*35238bceSAndroid Build Coastguard Worker 
120*35238bceSAndroid Build Coastguard Worker     void error(const std::string &what);
121*35238bceSAndroid Build Coastguard Worker 
122*35238bceSAndroid Build Coastguard Worker     enum State
123*35238bceSAndroid Build Coastguard Worker     {
124*35238bceSAndroid Build Coastguard Worker         STATE_DATA = 0,
125*35238bceSAndroid Build Coastguard Worker         STATE_TAG,
126*35238bceSAndroid Build Coastguard Worker         STATE_IDENTIFIER,
127*35238bceSAndroid Build Coastguard Worker         STATE_VALUE,
128*35238bceSAndroid Build Coastguard Worker         STATE_COMMENT,
129*35238bceSAndroid Build Coastguard Worker         STATE_ENTITY,
130*35238bceSAndroid Build Coastguard Worker 
131*35238bceSAndroid Build Coastguard Worker         STATE_LAST
132*35238bceSAndroid Build Coastguard Worker     };
133*35238bceSAndroid Build Coastguard Worker 
134*35238bceSAndroid Build Coastguard Worker     enum
135*35238bceSAndroid Build Coastguard Worker     {
136*35238bceSAndroid Build Coastguard Worker         END_OF_STRING = 0,         //!< End of string (0).
137*35238bceSAndroid Build Coastguard Worker         END_OF_BUFFER = 0xffffffff //!< End of current data buffer.
138*35238bceSAndroid Build Coastguard Worker     };
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker     Token m_curToken;  //!< Current token.
141*35238bceSAndroid Build Coastguard Worker     int m_curTokenLen; //!< Length of current token.
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker     State m_state; //!< Tokenization state.
144*35238bceSAndroid Build Coastguard Worker 
145*35238bceSAndroid Build Coastguard Worker     de::RingBuffer<uint8_t> m_buf;
146*35238bceSAndroid Build Coastguard Worker };
147*35238bceSAndroid Build Coastguard Worker 
148*35238bceSAndroid Build Coastguard Worker class Parser
149*35238bceSAndroid Build Coastguard Worker {
150*35238bceSAndroid Build Coastguard Worker public:
151*35238bceSAndroid Build Coastguard Worker     typedef std::map<std::string, std::string> AttributeMap;
152*35238bceSAndroid Build Coastguard Worker     typedef AttributeMap::const_iterator AttributeIter;
153*35238bceSAndroid Build Coastguard Worker 
154*35238bceSAndroid Build Coastguard Worker     Parser(void);
155*35238bceSAndroid Build Coastguard Worker     ~Parser(void);
156*35238bceSAndroid Build Coastguard Worker 
157*35238bceSAndroid Build Coastguard Worker     void clear(void); //!< Resets parser to initial state.
158*35238bceSAndroid Build Coastguard Worker 
159*35238bceSAndroid Build Coastguard Worker     void feed(const uint8_t *bytes, int numBytes);
160*35238bceSAndroid Build Coastguard Worker     void advance(void);
161*35238bceSAndroid Build Coastguard Worker 
getElement(void) const162*35238bceSAndroid Build Coastguard Worker     Element getElement(void) const
163*35238bceSAndroid Build Coastguard Worker     {
164*35238bceSAndroid Build Coastguard Worker         return m_element;
165*35238bceSAndroid Build Coastguard Worker     }
166*35238bceSAndroid Build Coastguard Worker 
167*35238bceSAndroid Build Coastguard Worker     // For ELEMENT_START / ELEMENT_END.
getElementName(void) const168*35238bceSAndroid Build Coastguard Worker     const char *getElementName(void) const
169*35238bceSAndroid Build Coastguard Worker     {
170*35238bceSAndroid Build Coastguard Worker         return m_elementName.c_str();
171*35238bceSAndroid Build Coastguard Worker     }
172*35238bceSAndroid Build Coastguard Worker 
173*35238bceSAndroid Build Coastguard Worker     // For ELEMENT_START.
hasAttribute(const char * name) const174*35238bceSAndroid Build Coastguard Worker     bool hasAttribute(const char *name) const
175*35238bceSAndroid Build Coastguard Worker     {
176*35238bceSAndroid Build Coastguard Worker         return m_attributes.find(name) != m_attributes.end();
177*35238bceSAndroid Build Coastguard Worker     }
getAttribute(const char * name) const178*35238bceSAndroid Build Coastguard Worker     const char *getAttribute(const char *name) const
179*35238bceSAndroid Build Coastguard Worker     {
180*35238bceSAndroid Build Coastguard Worker         return m_attributes.find(name)->second.c_str();
181*35238bceSAndroid Build Coastguard Worker     }
attributes(void) const182*35238bceSAndroid Build Coastguard Worker     const AttributeMap &attributes(void) const
183*35238bceSAndroid Build Coastguard Worker     {
184*35238bceSAndroid Build Coastguard Worker         return m_attributes;
185*35238bceSAndroid Build Coastguard Worker     }
186*35238bceSAndroid Build Coastguard Worker 
187*35238bceSAndroid Build Coastguard Worker     // For ELEMENT_DATA.
188*35238bceSAndroid Build Coastguard Worker     int getDataSize(void) const;
189*35238bceSAndroid Build Coastguard Worker     uint8_t getDataByte(int offset) const;
190*35238bceSAndroid Build Coastguard Worker     void getDataStr(std::string &dst) const;
191*35238bceSAndroid Build Coastguard Worker     void appendDataStr(std::string &dst) const;
192*35238bceSAndroid Build Coastguard Worker 
193*35238bceSAndroid Build Coastguard Worker private:
194*35238bceSAndroid Build Coastguard Worker     Parser(const Parser &other);
195*35238bceSAndroid Build Coastguard Worker     Parser &operator=(const Parser &other);
196*35238bceSAndroid Build Coastguard Worker 
197*35238bceSAndroid Build Coastguard Worker     void parseEntityValue(void);
198*35238bceSAndroid Build Coastguard Worker 
199*35238bceSAndroid Build Coastguard Worker     void error(const std::string &what);
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker     enum State
202*35238bceSAndroid Build Coastguard Worker     {
203*35238bceSAndroid Build Coastguard Worker         STATE_DATA = 0,                  //!< Initial state - assuming data or tag open.
204*35238bceSAndroid Build Coastguard Worker         STATE_ENTITY,                    //!< Parsed entity is stored - overrides data.
205*35238bceSAndroid Build Coastguard Worker         STATE_IN_PROCESSING_INSTRUCTION, //!< In processing instruction.
206*35238bceSAndroid Build Coastguard Worker         STATE_START_TAG_OPEN,            //!< Start tag open.
207*35238bceSAndroid Build Coastguard Worker         STATE_END_TAG_OPEN,              //!< End tag open.
208*35238bceSAndroid Build Coastguard Worker         STATE_EXPECTING_END_TAG_CLOSE,   //!< Expecting end tag close.
209*35238bceSAndroid Build Coastguard Worker         STATE_ATTRIBUTE_LIST,            //!< Expecting attribute list.
210*35238bceSAndroid Build Coastguard Worker         STATE_EXPECTING_ATTRIBUTE_EQ,    //!< Got attribute name, expecting =.
211*35238bceSAndroid Build Coastguard Worker         STATE_EXPECTING_ATTRIBUTE_VALUE, //!< Expecting attribute value.
212*35238bceSAndroid Build Coastguard Worker         STATE_YIELD_EMPTY_ELEMENT_END,   //!< Empty element: start has been reported but not end.
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker         STATE_LAST
215*35238bceSAndroid Build Coastguard Worker     };
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker     Tokenizer m_tokenizer;
218*35238bceSAndroid Build Coastguard Worker 
219*35238bceSAndroid Build Coastguard Worker     Element m_element;
220*35238bceSAndroid Build Coastguard Worker     std::string m_elementName;
221*35238bceSAndroid Build Coastguard Worker     AttributeMap m_attributes;
222*35238bceSAndroid Build Coastguard Worker 
223*35238bceSAndroid Build Coastguard Worker     State m_state;
224*35238bceSAndroid Build Coastguard Worker     std::string m_attribName;
225*35238bceSAndroid Build Coastguard Worker     std::string m_entityValue; //!< Data override, such as entity value.
226*35238bceSAndroid Build Coastguard Worker };
227*35238bceSAndroid Build Coastguard Worker 
228*35238bceSAndroid Build Coastguard Worker // Inline implementations
229*35238bceSAndroid Build Coastguard Worker 
getTokenStr(std::string & dst) const230*35238bceSAndroid Build Coastguard Worker inline void Tokenizer::getTokenStr(std::string &dst) const
231*35238bceSAndroid Build Coastguard Worker {
232*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_curToken != TOKEN_INCOMPLETE && m_curToken != TOKEN_END_OF_STRING);
233*35238bceSAndroid Build Coastguard Worker     dst.resize(m_curTokenLen);
234*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < m_curTokenLen; ndx++)
235*35238bceSAndroid Build Coastguard Worker         dst[ndx] = m_buf.peekBack(ndx);
236*35238bceSAndroid Build Coastguard Worker }
237*35238bceSAndroid Build Coastguard Worker 
appendTokenStr(std::string & dst) const238*35238bceSAndroid Build Coastguard Worker inline void Tokenizer::appendTokenStr(std::string &dst) const
239*35238bceSAndroid Build Coastguard Worker {
240*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_curToken != TOKEN_INCOMPLETE && m_curToken != TOKEN_END_OF_STRING);
241*35238bceSAndroid Build Coastguard Worker 
242*35238bceSAndroid Build Coastguard Worker     size_t oldLen = dst.size();
243*35238bceSAndroid Build Coastguard Worker     dst.resize(oldLen + m_curTokenLen);
244*35238bceSAndroid Build Coastguard Worker 
245*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < m_curTokenLen; ndx++)
246*35238bceSAndroid Build Coastguard Worker         dst[oldLen + ndx] = m_buf.peekBack(ndx);
247*35238bceSAndroid Build Coastguard Worker }
248*35238bceSAndroid Build Coastguard Worker 
getDataSize(void) const249*35238bceSAndroid Build Coastguard Worker inline int Parser::getDataSize(void) const
250*35238bceSAndroid Build Coastguard Worker {
251*35238bceSAndroid Build Coastguard Worker     if (m_state != STATE_ENTITY)
252*35238bceSAndroid Build Coastguard Worker         return m_tokenizer.getTokenLen();
253*35238bceSAndroid Build Coastguard Worker     else
254*35238bceSAndroid Build Coastguard Worker         return (int)m_entityValue.size();
255*35238bceSAndroid Build Coastguard Worker }
256*35238bceSAndroid Build Coastguard Worker 
getDataByte(int offset) const257*35238bceSAndroid Build Coastguard Worker inline uint8_t Parser::getDataByte(int offset) const
258*35238bceSAndroid Build Coastguard Worker {
259*35238bceSAndroid Build Coastguard Worker     if (m_state != STATE_ENTITY)
260*35238bceSAndroid Build Coastguard Worker         return m_tokenizer.getTokenByte(offset);
261*35238bceSAndroid Build Coastguard Worker     else
262*35238bceSAndroid Build Coastguard Worker         return (uint8_t)m_entityValue[offset];
263*35238bceSAndroid Build Coastguard Worker }
264*35238bceSAndroid Build Coastguard Worker 
getDataStr(std::string & dst) const265*35238bceSAndroid Build Coastguard Worker inline void Parser::getDataStr(std::string &dst) const
266*35238bceSAndroid Build Coastguard Worker {
267*35238bceSAndroid Build Coastguard Worker     if (m_state != STATE_ENTITY)
268*35238bceSAndroid Build Coastguard Worker         return m_tokenizer.getTokenStr(dst);
269*35238bceSAndroid Build Coastguard Worker     else
270*35238bceSAndroid Build Coastguard Worker         dst = m_entityValue;
271*35238bceSAndroid Build Coastguard Worker }
272*35238bceSAndroid Build Coastguard Worker 
appendDataStr(std::string & dst) const273*35238bceSAndroid Build Coastguard Worker inline void Parser::appendDataStr(std::string &dst) const
274*35238bceSAndroid Build Coastguard Worker {
275*35238bceSAndroid Build Coastguard Worker     if (m_state != STATE_ENTITY)
276*35238bceSAndroid Build Coastguard Worker         return m_tokenizer.appendTokenStr(dst);
277*35238bceSAndroid Build Coastguard Worker     else
278*35238bceSAndroid Build Coastguard Worker         dst += m_entityValue;
279*35238bceSAndroid Build Coastguard Worker }
280*35238bceSAndroid Build Coastguard Worker 
281*35238bceSAndroid Build Coastguard Worker } // namespace xml
282*35238bceSAndroid Build Coastguard Worker } // namespace xe
283*35238bceSAndroid Build Coastguard Worker 
284*35238bceSAndroid Build Coastguard Worker #endif // _XEXMLPARSER_HPP
285