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 * - " -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 &
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