[dali_2.3.20] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / json-parser-state.h
1 #ifndef DALI_JSON_PARSE_STATE_H
2 #define DALI_JSON_PARSE_STATE_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
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
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/public-api/dali-toolkit-common.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/devel-api/builder/tree-node.h>
26
27 #include <dali-toolkit/internal/builder/tree-node-manipulator.h>
28
29 namespace Dali
30 {
31 namespace Toolkit
32 {
33 namespace Internal
34 {
35 /**
36  * A safer std::advance()
37  */
38 template<typename IteratorType, typename EndIteratorType>
39 inline int AdvanceIter(IteratorType& iter, EndIteratorType& end, int n)
40 {
41   for(int i = 0; i < n; ++i)
42   {
43     if(iter == end)
44     {
45       return n - i;
46     }
47     ++iter;
48   }
49   return n;
50 }
51
52 /**
53  * Maintains parser state machine
54  *
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)
57  */
58 class JsonParserState
59 {
60 public:
61   /**
62    * Constructor
63    * @param tree Tree to start with, pass NULL if no existing tree
64    */
65   explicit JsonParserState(TreeNode* tree);
66
67   /**
68    * Parse json source
69    * The source is modified in place
70    * @param source The vector buffer to parse
71    * @return true if parsed successfully
72    */
73   bool ParseJson(VectorChar& source);
74
75   /**
76    * Get the root node
77    * @return The root TreeNode
78    */
79   TreeNode* GetRoot();
80
81   /**
82    * Get the error description of the last parse
83    * @return The error description or NULL if no error
84    */
85   const char* GetErrorDescription()
86   {
87     return mErrorDescription;
88   }
89
90   /**
91    * Get the error line number
92    * @return The line number of the error
93    */
94   int GetErrorLineNumber()
95   {
96     return mErrorNewLine;
97   }
98
99   /**
100    * Get the error column
101    * @return The error column
102    */
103   int GetErrorColumn()
104   {
105     return mErrorColumn;
106   }
107
108   /**
109    * Get the error position
110    * @return The error position
111    */
112   int GetErrorPosition()
113   {
114     return mErrorPosition;
115   }
116
117   /**
118    * Get the size of the string data that has been parsed
119    * @return The size of string data
120    */
121   int GetParsedStringSize()
122   {
123     return mNumberOfParsedChars;
124   };
125
126   /**
127    * Get the number of nodes created
128    * @return The number of nodes
129    */
130   int GetCreatedNodeCount()
131   {
132     return mNumberOfCreatedNodes;
133   };
134
135 private:
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
148
149   /**
150    * The current parse state
151    */
152   enum State
153   {
154     STATE_START,
155     STATE_OBJECT,
156     STATE_KEY,
157     STATE_VALUE,
158     STATE_END,
159   };
160
161   State mState;
162
163   // inhibited copy construct and assignment
164   JsonParserState(const JsonParserState&);
165   const JsonParserState& operator=(const JsonParserState&);
166
167   /**
168    * Parse over white space
169    * Increments the current position
170    * @return true if no parse errors
171    */
172   bool ParseWhiteSpace();
173
174   /**
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
178    */
179   bool ParseNumber();
180
181   /**
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
185    */
186   bool ParseSymbol(const std::string& symbol);
187
188   /**
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
192    */
193   bool ParseTrue();
194
195   /**
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
199    */
200   bool ParseFalse();
201
202   /**
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
206    */
207   bool ParseNULL();
208
209   /**
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
214    */
215   char* EncodeString();
216
217   /**
218    * Create a new node with name and type
219    */
220   TreeNode* CreateNewNode(const char* name, TreeNode::NodeType type);
221
222   /**
223    * Create a new node if first parse, else check if the node already
224    * exists and set it to a new type
225    */
226   TreeNode* NewNode(const char* name, TreeNode::NodeType type);
227
228   /**
229    * Set error meta data
230    * @returns always false.
231    */
232   bool Error(const char* description);
233
234   /**
235    * Reset state for another parse
236    */
237   void Reset();
238
239   /**
240    * Set current to its parent
241    * @return true if we had a parent, false and error otherwise
242    */
243   inline bool UpToParent()
244   {
245     if(NULL == mCurrent.GetParent())
246     {
247       return Error("Attempt to walk up above root");
248     }
249     mCurrent = TreeNodeManipulator(mCurrent.GetParent());
250     return true;
251   }
252
253   /**
254    * Get the current character
255    */
256   inline char Char()
257   {
258     return *mIter;
259   }
260
261   /**
262    * @return True if there are at least n character left
263    */
264   inline bool AtLeast(int n)
265   {
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;
270   }
271
272   /**
273    * @return True if at the end of the data to parse
274    */
275   inline bool AtEnd()
276   {
277     return mEnd == mIter;
278   }
279
280   /**
281    * Advance current position by n characters or stop at mEnd
282    */
283   inline void Advance(int n)
284   {
285     int c = AdvanceIter(mIter, mEnd, n);
286     mErrorPosition += c;
287     mErrorColumn += c;
288   }
289
290   /**
291    * Advance by n charaters and return true if we reached the end
292    */
293   inline bool AdvanceEnded(int n)
294   {
295     int c = AdvanceIter(mIter, mEnd, n);
296     mErrorPosition += c;
297     mErrorColumn += c;
298     return mEnd == mIter;
299   }
300
301   /**
302    * Advance by at least n characters (stopping at mEnd) and skip any whitespace after n.
303    */
304   inline void AdvanceSkipWhiteSpace(int n)
305   {
306     int c = AdvanceIter(mIter, mEnd, n);
307     mErrorPosition += c;
308     mErrorColumn += c;
309     static_cast<void>(ParseWhiteSpace());
310   }
311
312   /**
313    * Increment new line counters
314    */
315   inline void NewLine()
316   {
317     ++mErrorNewLine;
318     mErrorColumn = 0;
319   }
320
321   /**
322    * @brief Called by ParseJson if we are in STATE_START.
323    *
324    * @param[in] name The current name
325    * @param[in] currentChar The current character being parsed
326    * @return true if successfully parsed
327    */
328   bool HandleStartState(const char* name, const char currentChar);
329
330   /**
331    * @brief Called by ParseJson if we are in STATE_OBJECT.
332    *
333    * @param[in] currentChar The current character being parsed
334    * @param[in] lastCharacter The last character we parsed
335    * @return true if successfully parsed
336    */
337   bool HandleObjectState(const char currentChar, const char lastCharacter);
338
339   /**
340    * @brief Called by ParseJson if we are in STATE_KEY.
341    *
342    * @param[in/out] name A reference to the name variable
343    * @return true if successfully parsed
344    */
345   bool HandleKeyState(char*& name);
346
347   /**
348    * @brief Called by ParseJson if we are in STATE_VALUE.
349    *
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
354    */
355   bool HandleValueState(char*& name, const char currentChar, const char lastCharacter);
356
357   /**
358    * @brief Called by HandleValueState to parse a '"' character.
359    *
360    * @param[in] name The current name
361    * @return true if successfully parsed
362    */
363   bool HandleCharacterQuote(char*& name);
364
365   /**
366    * @brief Called by HandleValueState to parse a number or hyphen character.
367    *
368    * @param[in] name The current name
369    * @return true if successfully parsed
370    */
371   bool HandleCharacterNumberOrHyphen(const char* name);
372
373   /**
374    * @brief Called by HandleValueState to parse a '{' character.
375    *
376    * @param[in] name The current name
377    * @param[in] lastCharacter The last character we parsed
378    * @return true if successfully parsed
379    */
380   bool HandleCharacterBracesStart(const char* name, const char lastCharacter);
381
382   /**
383    * @brief Called by HandleValueState to parse a '}' character.
384    *
385    * @param[in] lastCharacter The last character we parsed
386    * @return true if successfully parsed
387    */
388   bool HandleCharacterBracesEnd(const char lastCharacter);
389
390   /**
391    * @brief Called by HandleValueState to parse a '[' character.
392    *
393    * @param[in] name The current name
394    * @return true if successfully parsed
395    */
396   bool HandleCharacterSquareBracketStart(const char* name);
397
398   /**
399    * @brief Called by HandleValueState to parse a ']' character.
400    *
401    * @param[in] lastCharacter The last character we parsed
402    * @return true if successfully parsed
403    */
404   bool HandleCharacterSquareBracketEnd(const char lastCharacter);
405
406   /**
407    * @brief Called by HandleValueState to parse a 't' character.
408    *
409    * @param[in] name The current name
410    * @return true if successfully parsed
411    */
412   bool HandleCharacterLowercaseT(const char* name);
413
414   /**
415    * @brief Called by HandleValueState to parse a 'n' character.
416    *
417    * @param[in] name The current name
418    * @return true if successfully parsed
419    */
420   bool HandleCharacterLowercaseN(const char* name);
421
422   /**
423    * @brief Called by HandleValueState to parse a 'f' character.
424    *
425    * @param[in] name The current name
426    * @return true if successfully parsed
427    */
428   bool HandleCharacterLowercaseF(const char* name);
429
430   /**
431    * @brief Called by HandleValueState to parse a ',' character.
432    *
433    * @param[in] name The current name
434    * @return true if successfully parsed
435    */
436   bool HandleCharacterComma(const char* name);
437 };
438
439 } // namespace Internal
440
441 } // namespace Toolkit
442
443 } // namespace Dali
444
445 #endif // DALI_JSON_PARSE_STATE_H