[SRUK] Initial copy from Tizen 2.2 version
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / tree-node-manipulator.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // EXTERNAL INCLUDES
18 #include <cstring>
19 #include <sstream>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/builder/tree-node-manipulator.h>
23
24 #include <dali-toolkit/public-api/builder/tree-node.h>
25
26 namespace Dali
27 {
28
29 namespace Toolkit
30 {
31
32 namespace Internal
33 {
34
35 namespace
36 {
37
38 void Indent(std::ostream& o, int indent)
39 {
40   for (int i = 0; i < indent; ++i)
41   {
42     o << " ";
43   }
44 }
45
46 }
47
48 TreeNodeManipulator::TreeNodeManipulator(TreeNode* node)
49   : mNode(node)
50 {
51 }
52
53 TreeNode* TreeNodeManipulator::NewTreeNode()
54 {
55   return new TreeNode();
56 }
57
58 void TreeNodeManipulator::ShallowCopy(const TreeNode* from, TreeNode* to)
59 {
60   DALI_ASSERT_DEBUG(from);
61   DALI_ASSERT_DEBUG(to);
62
63   if( from )
64   {
65     to->mName         = from->mName;
66     to->mType         = from->mType;
67     to->mSubstituion  = from->mSubstituion;
68     switch(from->mType)
69     {
70       case TreeNode::INTEGER:
71       {
72         to->mIntValue = from->mIntValue;
73         break;
74       }
75       case TreeNode::FLOAT:
76       {
77         to->mFloatValue = from->mFloatValue;
78         break;
79       }
80       case TreeNode::STRING:
81       {
82         to->mStringValue = from->mStringValue;
83         break;
84       }
85       case TreeNode::BOOLEAN:
86       {
87         to->mIntValue = from->mIntValue;
88         break;
89       }
90       case TreeNode::IS_NULL:
91       case TreeNode::OBJECT:
92       case TreeNode::ARRAY:
93       {
94         break;
95       }
96     }
97   }
98
99 }
100
101 void TreeNodeManipulator::MoveNodeStrings(VectorCharIter& start, const VectorCharIter& sentinel)
102 {
103   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
104   if(mNode->mName)
105   {
106     mNode->mName = CopyString(mNode->mName, start, sentinel);
107   }
108
109   if(TreeNode::STRING == mNode->mType)
110   {
111     mNode->mStringValue = CopyString(mNode->mStringValue, start, sentinel);
112   }
113 }
114
115 void TreeNodeManipulator::MoveStrings(VectorCharIter& start, const VectorCharIter& sentinel)
116 {
117   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
118   TreeNodeManipulator modify(mNode);
119   modify.MoveNodeStrings(start, sentinel);
120   RecurseMoveChildStrings(start, sentinel);
121 }
122
123 void TreeNodeManipulator::RecurseMoveChildStrings(VectorCharIter& start, const VectorCharIter& sentinel)
124 {
125   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
126
127   TreeNode* child = mNode->mFirstChild;
128   while(child)
129   {
130     TreeNodeManipulator manipChild(child);
131     manipChild.MoveNodeStrings(start, sentinel);
132     child = child->mNextSibling;
133   }
134
135   child = mNode->mFirstChild;
136   while(child)
137   {
138     TreeNodeManipulator manipChild(child);
139     manipChild.RecurseMoveChildStrings(start, sentinel);
140     child = child->mNextSibling;
141   }
142 }
143
144 void TreeNodeManipulator::RemoveChildren()
145 {
146   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
147
148   CollectNodes collector;
149
150   DepthFirst( mNode, collector );
151
152   for(CollectNodes::iterator iter = collector.nodes.begin(); iter != collector.nodes.end(); ++iter)
153   {
154     if( *iter != mNode)
155     {
156       delete *iter;
157     }
158   }
159
160   mNode->mFirstChild = NULL;
161   mNode->mLastChild  = NULL;
162 }
163
164 TreeNode* TreeNodeManipulator::Copy(const TreeNode& tree, int& numberNodes, int& numberChars)
165 {
166   TreeNode* root = NewTreeNode();
167
168   ShallowCopy(&tree, root);
169
170   if(tree.mName)
171   {
172     numberChars += std::strlen(tree.mName);
173   }
174
175   if(TreeNode::STRING == tree.mType)
176   {
177     numberChars += std::strlen(tree.mStringValue);
178   }
179
180   ++numberNodes;
181
182   CopyChildren(&tree, root, numberNodes, numberChars);
183
184   return root;
185 }
186
187 void TreeNodeManipulator::CopyChildren(const TreeNode* from, TreeNode* to, int& numberNodes, int& numberChars)
188 {
189   DALI_ASSERT_DEBUG(from && "Operation on NULL JSON node");
190   DALI_ASSERT_DEBUG(to);
191
192   for( TreeNode::ConstIterator iter = from->CBegin(); iter != from->CEnd(); ++iter)
193   {
194     const TreeNode* child = &((*iter).second);
195     if(child->mName)
196     {
197       numberChars += std::strlen(child->mName) + 1;
198     }
199
200     if(TreeNode::STRING == child->mType)
201     {
202       numberChars += std::strlen(child->mStringValue) + 1;
203     }
204
205     TreeNode* newNode = NewTreeNode();
206
207     ShallowCopy(child, newNode);
208
209     TreeNodeManipulator modify(to);
210
211     modify.AddChild(newNode);
212
213     ++numberNodes;
214
215     CopyChildren(child, newNode, numberNodes, numberChars);
216   }
217 }
218
219 TreeNode *TreeNodeManipulator::AddChild(TreeNode *rhs)
220 {
221   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
222
223   rhs->mParent = mNode;
224   if (mNode->mLastChild)
225   {
226     mNode->mLastChild = mNode->mLastChild->mNextSibling = rhs;
227   }
228   else
229   {
230     mNode->mFirstChild = mNode->mLastChild = rhs;
231   }
232   return rhs;
233 }
234
235 TreeNode::NodeType TreeNodeManipulator::GetType() const
236 {
237   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
238
239   return mNode->GetType();
240 }
241
242 size_t TreeNodeManipulator::Size() const
243 {
244   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
245
246   return mNode->Size();
247 }
248
249 void TreeNodeManipulator::SetType( TreeNode::NodeType type)
250 {
251   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
252
253   if( mNode->mType != type )
254   {
255     mNode->mType = type;
256
257     if( NULL != mNode->mFirstChild )
258     {
259       // value types have no children
260       bool removeChildren = ! (TreeNode::OBJECT == type || TreeNode::ARRAY == type);
261
262       // ie if swapping array for object
263       removeChildren = (removeChildren == true) ? true : type != mNode->mType;
264
265       // so remove any children
266       if( removeChildren && NULL != mNode->mFirstChild)
267       {
268         RemoveChildren();
269       }
270     }
271   }
272 }
273
274 void TreeNodeManipulator::SetName( const char* name )
275 {
276   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
277   mNode->mName = name;
278 }
279
280 void TreeNodeManipulator::SetSubstitution( bool b )
281 {
282   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
283   mNode->mSubstituion = b;
284 }
285
286 TreeNode* TreeNodeManipulator::GetParent() const
287 {
288   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
289   return NULL == mNode ? NULL : mNode->mParent;
290 }
291
292 const TreeNode* TreeNodeManipulator::GetChild(const std::string& name) const
293 {
294   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
295   return NULL == mNode ? NULL : mNode->GetChild(name);
296 }
297
298 void TreeNodeManipulator::SetString( const char* string )
299 {
300   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
301   SetType(TreeNode::STRING);
302   mNode->mStringValue = string;
303 }
304
305 void TreeNodeManipulator::SetInteger( int i )
306 {
307   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
308   SetType(TreeNode::INTEGER);
309   mNode->mIntValue = i;
310 }
311
312 void TreeNodeManipulator::SetFloat( float f )
313 {
314   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
315   SetType(TreeNode::FLOAT);
316   mNode->mFloatValue = f;
317 }
318
319 void TreeNodeManipulator::SetBoolean( bool b )
320 {
321   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
322   SetType(TreeNode::BOOLEAN);
323   mNode->mIntValue = b == true ? 1 : 0;
324 }
325
326 void TreeNodeManipulator::Write(std::ostream& output, int indent) const
327 {
328   DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
329   DoWrite(mNode, output, indent);
330 }
331
332 void TreeNodeManipulator::DoWrite(const TreeNode *value, std::ostream& output, int indent) const
333 {
334   DALI_ASSERT_DEBUG(value && "Operation on NULL JSON node");
335
336   Indent(output, indent);
337
338   if (value->GetName())
339   {
340     output << "\"" << value->GetName() << "\":";
341   }
342
343   switch(value->GetType())
344   {
345     case TreeNode::IS_NULL:
346     {
347       output << "null";
348       if(NULL != value->mNextSibling)
349       {
350         output << ",";
351       }
352       if(indent)
353       {
354         output << std::endl;
355       }
356       break;
357     }
358     case TreeNode::OBJECT:
359     case TreeNode::ARRAY:
360     {
361       if( value->GetType() == TreeNode::OBJECT)
362       {
363         output << "{";
364         if(indent)
365         {
366           output << std::endl;
367         }
368       }
369       else
370       {
371         output << "[";
372         if(indent)
373         {
374           output << std::endl;
375         }
376       }
377
378       for (TreeNode::ConstIterator it = value->CBegin(); it != value->CEnd(); ++it)
379       {
380         DoWrite( &((*it).second), output, indent + 1);
381       }
382       Indent(output, indent);
383       if( value->GetType() == TreeNode::OBJECT )
384       {
385         output << "}";
386         if(indent)
387         {
388           output << std::endl;
389         }
390       }
391       else
392       {
393         output << "]";
394         if(indent)
395         {
396           output << std::endl;
397         }
398       }
399       break;
400     }
401     case TreeNode::STRING:
402     {
403       output << "\"" << value->GetString() << "\"";
404       if(NULL != value->mNextSibling)
405       {
406         output << ",";
407       }
408       if(indent)
409       {
410         output << std::endl;
411       }
412
413       break;
414     }
415     case TreeNode::INTEGER:
416     {
417       output << value->GetInteger();
418       if(NULL != value->mNextSibling)
419       {
420         output << ",";
421       }
422       if(indent)
423       {
424         output << std::endl;
425       }
426
427       break;
428     }
429     case TreeNode::FLOAT:
430     {
431       output.setf( std::ios::floatfield );
432       output << value->GetFloat();
433       output.unsetf( std::ios::floatfield );
434       if(NULL != value->mNextSibling)
435       {
436         output << ",";
437       }
438       if(indent)
439       {
440         output << std::endl;
441       }
442       break;
443     }
444     case TreeNode::BOOLEAN:
445     {
446       if( value->GetInteger() )
447       {
448         output << "true";
449       }
450       else
451       {
452         output << "false";
453       }
454       if(NULL != value->mNextSibling)
455       {
456         output << ",";
457       }
458       if(indent)
459       {
460         output << std::endl;
461       }
462
463       break;
464     }
465   } // switch
466 } // DoWrite
467
468
469 const TreeNode* FindIt(const std::string& childName, const TreeNode* node)
470 {
471   DALI_ASSERT_DEBUG(node);
472
473   const TreeNode* found = NULL;
474
475   if( node )
476   {
477     if( NULL != (found = node->GetChild(childName)) )
478     {
479       return found;
480     }
481     else
482     {
483       for(TreeNode::ConstIterator iter = node->CBegin(); iter != node->CEnd(); ++iter)
484       {
485         if( NULL != (found = FindIt(childName, &((*iter).second)) ) )
486         {
487           return found;
488         }
489       }
490     }
491   }
492   return found;
493 }
494
495 char *CopyString( const char *fromString, VectorCharIter& iter, const VectorCharIter& sentinel)
496 {
497   DALI_ASSERT_DEBUG(fromString);
498   DALI_ASSERT_DEBUG(iter != sentinel);
499
500   char *start= &(*iter);
501   const char *ptr = fromString;
502
503   if(ptr)
504   {
505     while(*ptr != 0)
506     {
507       DALI_ASSERT_DEBUG(iter != sentinel);
508       *iter++ = *ptr++;
509     }
510
511     *iter++ = 0;
512   }
513   return start;
514 }
515
516
517 } // namespace internal
518
519 } // namespace Toolkit
520
521 } // namespace Dali
522