1 #ifndef _XEXMLPARSER_HPP
2 #define _XEXMLPARSER_HPP
3 /*-------------------------------------------------------------------------
4 * drawElements Quality Program Test Executor
5 * ------------------------------------------
7 * Copyright 2014 The Android Open Source Project
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
25 * \todo [2012-06-07 pyry] Not supported / handled properly:
26 * - xml namespaces (<ns:Element>)
27 * - backslash escapes in strings
28 * - " -style escapes
30 *//*--------------------------------------------------------------------*/
33 #include "deRingBuffer.hpp"
45 TOKEN_INCOMPLETE = 0, //!< Not enough data to determine token.
46 TOKEN_END_OF_STRING, //!< End of document string.
47 TOKEN_DATA, //!< Block of data (anything outside tags).
48 TOKEN_COMMENT, //!< <!-- comment -->
49 TOKEN_IDENTIFIER, //!< Identifier (in tags).
50 TOKEN_STRING, //!< String (in tags).
51 TOKEN_TAG_START, //!< <
53 TOKEN_END_TAG_START, //!< </
54 TOKEN_EMPTY_ELEMENT_END, //!< />
55 TOKEN_PROCESSING_INSTRUCTION_START, //!< <?
56 TOKEN_PROCESSING_INSTRUCTION_END, //!< ?>
58 TOKEN_ENTITY, //!< Entity reference, such as &
65 ELEMENT_INCOMPLETE = 0, //!< Incomplete element.
66 ELEMENT_START, //!< Element start.
67 ELEMENT_END, //!< Element end.
68 ELEMENT_DATA, //!< Data element.
69 ELEMENT_END_OF_STRING, //!< End of document string.
74 const char* getTokenName (Token token);
76 // \todo [2012-10-17 pyry] Add line number etc.
77 class ParseError : public xe::ParseError
80 ParseError (const std::string& message) : xe::ParseError(message) {}
89 void clear (void); //!< Resets tokenizer to initial state.
91 void feed (const deUint8* bytes, int numBytes);
94 Token getToken (void) const { return m_curToken; }
95 int getTokenLen (void) const { return m_curTokenLen; }
96 deUint8 getTokenByte (int offset) const { DE_ASSERT(m_curToken != TOKEN_INCOMPLETE && m_curToken != TOKEN_END_OF_STRING); return m_buf.peekBack(offset); }
97 void getTokenStr (std::string& dst) const;
98 void appendTokenStr (std::string& dst) const;
100 void getString (std::string& dst) const;
103 Tokenizer (const Tokenizer& other);
104 Tokenizer& operator= (const Tokenizer& other);
106 int getChar (int offset) const;
108 void error (const std::string& what);
124 END_OF_STRING = 0, //!< End of string (0).
125 END_OF_BUFFER = 0xffffffff //!< End of current data buffer.
128 Token m_curToken; //!< Current token.
129 int m_curTokenLen; //!< Length of current token.
131 State m_state; //!< Tokenization state.
133 de::RingBuffer<deUint8> m_buf;
139 typedef std::map<std::string, std::string> AttributeMap;
140 typedef AttributeMap::const_iterator AttributeIter;
145 void clear (void); //!< Resets parser to initial state.
147 void feed (const deUint8* bytes, int numBytes);
150 Element getElement (void) const { return m_element; }
152 // For ELEMENT_START / ELEMENT_END.
153 const char* getElementName (void) const { return m_elementName.c_str(); }
155 // For ELEMENT_START.
156 bool hasAttribute (const char* name) const { return m_attributes.find(name) != m_attributes.end(); }
157 const char* getAttribute (const char* name) const { return m_attributes.find(name)->second.c_str(); }
158 const AttributeMap& attributes (void) const { return m_attributes; }
161 int getDataSize (void) const;
162 deUint8 getDataByte (int offset) const;
163 void getDataStr (std::string& dst) const;
164 void appendDataStr (std::string& dst) const;
167 Parser (const Parser& other);
168 Parser& operator= (const Parser& other);
170 void parseEntityValue (void);
172 void error (const std::string& what);
176 STATE_DATA = 0, //!< Initial state - assuming data or tag open.
177 STATE_ENTITY, //!< Parsed entity is stored - overrides data.
178 STATE_IN_PROCESSING_INSTRUCTION, //!< In processing instruction.
179 STATE_START_TAG_OPEN, //!< Start tag open.
180 STATE_END_TAG_OPEN, //!< End tag open.
181 STATE_EXPECTING_END_TAG_CLOSE, //!< Expecting end tag close.
182 STATE_ATTRIBUTE_LIST, //!< Expecting attribute list.
183 STATE_EXPECTING_ATTRIBUTE_EQ, //!< Got attribute name, expecting =.
184 STATE_EXPECTING_ATTRIBUTE_VALUE, //!< Expecting attribute value.
185 STATE_YIELD_EMPTY_ELEMENT_END, //!< Empty element: start has been reported but not end.
190 Tokenizer m_tokenizer;
193 std::string m_elementName;
194 AttributeMap m_attributes;
197 std::string m_attribName;
198 std::string m_entityValue; //!< Data override, such as entity value.
201 // Inline implementations
203 inline void Tokenizer::getTokenStr (std::string& dst) const
205 DE_ASSERT(m_curToken != TOKEN_INCOMPLETE && m_curToken != TOKEN_END_OF_STRING);
206 dst.resize(m_curTokenLen);
207 for (int ndx = 0; ndx < m_curTokenLen; ndx++)
208 dst[ndx] = m_buf.peekBack(ndx);
211 inline void Tokenizer::appendTokenStr (std::string& dst) const
213 DE_ASSERT(m_curToken != TOKEN_INCOMPLETE && m_curToken != TOKEN_END_OF_STRING);
215 size_t oldLen = dst.size();
216 dst.resize(oldLen+m_curTokenLen);
218 for (int ndx = 0; ndx < m_curTokenLen; ndx++)
219 dst[oldLen+ndx] = m_buf.peekBack(ndx);
222 inline int Parser::getDataSize (void) const
224 if (m_state != STATE_ENTITY)
225 return m_tokenizer.getTokenLen();
227 return (int)m_entityValue.size();
230 inline deUint8 Parser::getDataByte (int offset) const
232 if (m_state != STATE_ENTITY)
233 return m_tokenizer.getTokenByte(offset);
235 return (deUint8)m_entityValue[offset];
238 inline void Parser::getDataStr (std::string& dst) const
240 if (m_state != STATE_ENTITY)
241 return m_tokenizer.getTokenStr(dst);
246 inline void Parser::appendDataStr (std::string& dst) const
248 if (m_state != STATE_ENTITY)
249 return m_tokenizer.appendTokenStr(dst);
251 dst += m_entityValue;
257 #endif // _XEXMLPARSER_HPP