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