1 #ifndef DALI_JSON_PARSE_STATE_H
2 #define DALI_JSON_PARSE_STATE_H
5 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <dali-toolkit/public-api/dali-toolkit-common.h>
25 #include <dali-toolkit/devel-api/builder/tree-node.h>
27 #include <dali-toolkit/internal/builder/tree-node-manipulator.h>
36 * A safer std::advance()
38 template<typename IteratorType, typename EndIteratorType>
39 inline int AdvanceIter(IteratorType& iter, EndIteratorType& end, int n)
41 for(int i = 0; i < n; ++i)
53 * Maintains parser state machine
55 * If a NULL root node is passed in the constructor then a faster non merging parse is performed (the first pass).
56 * Otherwise the json tree is merged (and requires slower searching)
63 * @param tree Tree to start with, pass NULL if no existing tree
65 explicit JsonParserState(TreeNode* tree);
69 * The source is modified in place
70 * @param source The vector buffer to parse
71 * @return true if parsed successfully
73 bool ParseJson(VectorChar& source);
77 * @return The root TreeNode
82 * Get the error description of the last parse
83 * @return The error description or NULL if no error
85 const char* GetErrorDescription()
87 return mErrorDescription;
91 * Get the error line number
92 * @return The line number of the error
94 int GetErrorLineNumber()
100 * Get the error column
101 * @return The error column
109 * Get the error position
110 * @return The error position
112 int GetErrorPosition()
114 return mErrorPosition;
118 * Get the size of the string data that has been parsed
119 * @return The size of string data
121 int GetParsedStringSize()
123 return mNumberOfParsedChars;
127 * Get the number of nodes created
128 * @return The number of nodes
130 int GetCreatedNodeCount()
132 return mNumberOfCreatedNodes;
136 VectorCharIter mIter; ///< Current position
137 VectorCharIter mStart; ///< Start position
138 VectorCharIter mEnd; ///< End of buffer being parsed
139 TreeNode* mRoot; ///< Root node created
140 TreeNodeManipulator mCurrent; ///< The Current modifiable node
141 const char* mErrorDescription; ///< The error description if set
142 int mErrorNewLine; ///< The error line number
143 int mErrorColumn; ///< The error column
144 int mErrorPosition; ///< The error position
145 int mNumberOfParsedChars; ///< The size of string data
146 int mNumberOfCreatedNodes; ///< The number of nodes created
147 bool mFirstParse; ///< Flag if first parse
150 * The current parse state
163 // inhibited copy construct and assignment
164 JsonParserState(const JsonParserState&);
165 const JsonParserState& operator=(const JsonParserState&);
168 * Parse over white space
169 * Increments the current position
170 * @return true if no parse errors
172 bool ParseWhiteSpace();
175 * Parse over a number, setting the current node if found
176 * Increments the current position. Sets error data if parse error.
177 * @return true if found, false if parse error
182 * Parse over a symbol
183 * Increments the current position. Sets error data if parse error.
184 * @return true if found, false if parse error
186 bool ParseSymbol(const std::string& symbol);
189 * Parse over 'true' symbol, setting the current node if found
190 * Increments the current position. Sets error data if parse error.
191 * @return true if found, false if parse error
196 * Parse over 'false' symbol, setting the current node if found
197 * Increments the current position. Sets error data if parse error.
198 * @return true if found, false if parse error
203 * Parse over 'null' symbol, setting the current node if found
204 * Increments the current position. Sets error data if parse error.
205 * @return true if found, false if parse error
210 * Parse over a string from the current position and insert escaped
211 * control characters in place in the string and a null terminator.
212 * This function works from and modifes the current buffer position.
213 * @return the start of the null terminated string
215 char* EncodeString();
218 * Create a new node with name and type
220 TreeNode* CreateNewNode(const char* name, TreeNode::NodeType type);
223 * Create a new node if first parse, else check if the node already
224 * exists and set it to a new type
226 TreeNode* NewNode(const char* name, TreeNode::NodeType type);
229 * Set error meta data
230 * @returns always false.
232 bool Error(const char* description);
235 * Reset state for another parse
240 * Set current to its parent
241 * @return true if we had a parent, false and error otherwise
243 inline bool UpToParent()
245 if(NULL == mCurrent.GetParent())
247 return Error("Attempt to walk up above root");
249 mCurrent = TreeNodeManipulator(mCurrent.GetParent());
254 * Get the current character
262 * @return True if there are at least n character left
264 inline bool AtLeast(int n)
266 // The standard suggests vector.end() can be decremented as
267 // iter v.back() { *--v.end() }
268 // (ISO/IEC 14882:2003 C++ Standard 23.1.1/12 – Sequences)
269 return (mEnd - mIter) > n;
273 * @return True if at the end of the data to parse
277 return mEnd == mIter;
281 * Advance current position by n characters or stop at mEnd
283 inline void Advance(int n)
285 int c = AdvanceIter(mIter, mEnd, n);
291 * Advance by n charaters and return true if we reached the end
293 inline bool AdvanceEnded(int n)
295 int c = AdvanceIter(mIter, mEnd, n);
298 return mEnd == mIter;
302 * Advance by at least n characters (stopping at mEnd) and skip any whitespace after n.
304 inline void AdvanceSkipWhiteSpace(int n)
306 int c = AdvanceIter(mIter, mEnd, n);
309 static_cast<void>(ParseWhiteSpace());
313 * Increment new line counters
315 inline void NewLine()
322 * @brief Called by ParseJson if we are in STATE_START.
324 * @param[in] name The current name
325 * @param[in] currentChar The current character being parsed
326 * @return true if successfully parsed
328 bool HandleStartState(const char* name, const char currentChar);
331 * @brief Called by ParseJson if we are in STATE_OBJECT.
333 * @param[in] currentChar The current character being parsed
334 * @param[in] lastCharacter The last character we parsed
335 * @return true if successfully parsed
337 bool HandleObjectState(const char currentChar, const char lastCharacter);
340 * @brief Called by ParseJson if we are in STATE_KEY.
342 * @param[in/out] name A reference to the name variable
343 * @return true if successfully parsed
345 bool HandleKeyState(char*& name);
348 * @brief Called by ParseJson if we are in STATE_VALUE.
350 * @param[in/out] name A reference to the name variable
351 * @param[in] currentChar The current character being parsed
352 * @param[in] lastCharacter The last character we parsed
353 * @return true if successfully parsed
355 bool HandleValueState(char*& name, const char currentChar, const char lastCharacter);
358 * @brief Called by HandleValueState to parse a '"' character.
360 * @param[in] name The current name
361 * @return true if successfully parsed
363 bool HandleCharacterQuote(char*& name);
366 * @brief Called by HandleValueState to parse a number or hyphen character.
368 * @param[in] name The current name
369 * @return true if successfully parsed
371 bool HandleCharacterNumberOrHyphen(const char* name);
374 * @brief Called by HandleValueState to parse a '{' character.
376 * @param[in] name The current name
377 * @param[in] lastCharacter The last character we parsed
378 * @return true if successfully parsed
380 bool HandleCharacterBracesStart(const char* name, const char lastCharacter);
383 * @brief Called by HandleValueState to parse a '}' character.
385 * @param[in] lastCharacter The last character we parsed
386 * @return true if successfully parsed
388 bool HandleCharacterBracesEnd(const char lastCharacter);
391 * @brief Called by HandleValueState to parse a '[' character.
393 * @param[in] name The current name
394 * @return true if successfully parsed
396 bool HandleCharacterSquareBracketStart(const char* name);
399 * @brief Called by HandleValueState to parse a ']' character.
401 * @param[in] lastCharacter The last character we parsed
402 * @return true if successfully parsed
404 bool HandleCharacterSquareBracketEnd(const char lastCharacter);
407 * @brief Called by HandleValueState to parse a 't' character.
409 * @param[in] name The current name
410 * @return true if successfully parsed
412 bool HandleCharacterLowercaseT(const char* name);
415 * @brief Called by HandleValueState to parse a 'n' character.
417 * @param[in] name The current name
418 * @return true if successfully parsed
420 bool HandleCharacterLowercaseN(const char* name);
423 * @brief Called by HandleValueState to parse a 'f' character.
425 * @param[in] name The current name
426 * @return true if successfully parsed
428 bool HandleCharacterLowercaseF(const char* name);
431 * @brief Called by HandleValueState to parse a ',' character.
433 * @param[in] name The current name
434 * @return true if successfully parsed
436 bool HandleCharacterComma(const char* name);
439 } // namespace Internal
441 } // namespace Toolkit
445 #endif // DALI_JSON_PARSE_STATE_H