2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
22 #include <dali-toolkit/internal/builder/tree-node-manipulator.h>
24 #include <dali-toolkit/public-api/builder/tree-node.h>
38 void Indent(std::ostream& o, int indent)
40 for (int i = 0; i < indent; ++i)
48 TreeNodeManipulator::TreeNodeManipulator(TreeNode* node)
53 TreeNode* TreeNodeManipulator::NewTreeNode()
55 return new TreeNode();
58 void TreeNodeManipulator::ShallowCopy(const TreeNode* from, TreeNode* to)
60 DALI_ASSERT_DEBUG(from);
61 DALI_ASSERT_DEBUG(to);
65 to->mName = from->mName;
66 to->mType = from->mType;
67 to->mSubstituion = from->mSubstituion;
70 case TreeNode::INTEGER:
72 to->mIntValue = from->mIntValue;
77 to->mFloatValue = from->mFloatValue;
80 case TreeNode::STRING:
82 to->mStringValue = from->mStringValue;
85 case TreeNode::BOOLEAN:
87 to->mIntValue = from->mIntValue;
90 case TreeNode::IS_NULL:
91 case TreeNode::OBJECT:
101 void TreeNodeManipulator::MoveNodeStrings(VectorCharIter& start, const VectorCharIter& sentinel)
103 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
106 mNode->mName = CopyString(mNode->mName, start, sentinel);
109 if(TreeNode::STRING == mNode->mType)
111 mNode->mStringValue = CopyString(mNode->mStringValue, start, sentinel);
115 void TreeNodeManipulator::MoveStrings(VectorCharIter& start, const VectorCharIter& sentinel)
117 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
118 TreeNodeManipulator modify(mNode);
119 modify.MoveNodeStrings(start, sentinel);
120 RecurseMoveChildStrings(start, sentinel);
123 void TreeNodeManipulator::RecurseMoveChildStrings(VectorCharIter& start, const VectorCharIter& sentinel)
125 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
127 TreeNode* child = mNode->mFirstChild;
130 TreeNodeManipulator manipChild(child);
131 manipChild.MoveNodeStrings(start, sentinel);
132 child = child->mNextSibling;
135 child = mNode->mFirstChild;
138 TreeNodeManipulator manipChild(child);
139 manipChild.RecurseMoveChildStrings(start, sentinel);
140 child = child->mNextSibling;
144 void TreeNodeManipulator::RemoveChildren()
146 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
148 CollectNodes collector;
150 DepthFirst( mNode, collector );
152 for(CollectNodes::iterator iter = collector.nodes.begin(); iter != collector.nodes.end(); ++iter)
160 mNode->mFirstChild = NULL;
161 mNode->mLastChild = NULL;
164 TreeNode* TreeNodeManipulator::Copy(const TreeNode& tree, int& numberNodes, int& numberChars)
166 TreeNode* root = NewTreeNode();
168 ShallowCopy(&tree, root);
172 numberChars += std::strlen(tree.mName);
175 if(TreeNode::STRING == tree.mType)
177 numberChars += std::strlen(tree.mStringValue);
182 CopyChildren(&tree, root, numberNodes, numberChars);
187 void TreeNodeManipulator::CopyChildren(const TreeNode* from, TreeNode* to, int& numberNodes, int& numberChars)
189 DALI_ASSERT_DEBUG(from && "Operation on NULL JSON node");
190 DALI_ASSERT_DEBUG(to);
192 for( TreeNode::ConstIterator iter = from->CBegin(); iter != from->CEnd(); ++iter)
194 const TreeNode* child = &((*iter).second);
197 numberChars += std::strlen(child->mName) + 1;
200 if(TreeNode::STRING == child->mType)
202 numberChars += std::strlen(child->mStringValue) + 1;
205 TreeNode* newNode = NewTreeNode();
207 ShallowCopy(child, newNode);
209 TreeNodeManipulator modify(to);
211 modify.AddChild(newNode);
215 CopyChildren(child, newNode, numberNodes, numberChars);
219 TreeNode *TreeNodeManipulator::AddChild(TreeNode *rhs)
221 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
223 rhs->mParent = mNode;
224 if (mNode->mLastChild)
226 mNode->mLastChild = mNode->mLastChild->mNextSibling = rhs;
230 mNode->mFirstChild = mNode->mLastChild = rhs;
235 TreeNode::NodeType TreeNodeManipulator::GetType() const
237 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
239 return mNode->GetType();
242 size_t TreeNodeManipulator::Size() const
244 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
246 return mNode->Size();
249 void TreeNodeManipulator::SetType( TreeNode::NodeType type)
251 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
253 if( mNode->mType != type )
257 if( NULL != mNode->mFirstChild )
259 // value types have no children
260 bool removeChildren = ! (TreeNode::OBJECT == type || TreeNode::ARRAY == type);
262 // ie if swapping array for object
263 removeChildren = (removeChildren == true) ? true : type != mNode->mType;
265 // so remove any children
266 if( removeChildren && NULL != mNode->mFirstChild)
274 void TreeNodeManipulator::SetName( const char* name )
276 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
280 void TreeNodeManipulator::SetSubstitution( bool b )
282 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
283 mNode->mSubstituion = b;
286 TreeNode* TreeNodeManipulator::GetParent() const
288 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
289 return NULL == mNode ? NULL : mNode->mParent;
292 const TreeNode* TreeNodeManipulator::GetChild(const std::string& name) const
294 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
295 return NULL == mNode ? NULL : mNode->GetChild(name);
298 void TreeNodeManipulator::SetString( const char* string )
300 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
301 SetType(TreeNode::STRING);
302 mNode->mStringValue = string;
305 void TreeNodeManipulator::SetInteger( int i )
307 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
308 SetType(TreeNode::INTEGER);
309 mNode->mIntValue = i;
312 void TreeNodeManipulator::SetFloat( float f )
314 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
315 SetType(TreeNode::FLOAT);
316 mNode->mFloatValue = f;
319 void TreeNodeManipulator::SetBoolean( bool b )
321 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
322 SetType(TreeNode::BOOLEAN);
323 mNode->mIntValue = b == true ? 1 : 0;
326 void TreeNodeManipulator::Write(std::ostream& output, int indent) const
328 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
329 DoWrite(mNode, output, indent);
332 void TreeNodeManipulator::DoWrite(const TreeNode *value, std::ostream& output, int indent) const
334 DALI_ASSERT_DEBUG(value && "Operation on NULL JSON node");
336 Indent(output, indent);
338 if (value->GetName())
340 output << "\"" << value->GetName() << "\":";
343 switch(value->GetType())
345 case TreeNode::IS_NULL:
348 if(NULL != value->mNextSibling)
358 case TreeNode::OBJECT:
359 case TreeNode::ARRAY:
361 if( value->GetType() == TreeNode::OBJECT)
378 for (TreeNode::ConstIterator it = value->CBegin(); it != value->CEnd(); ++it)
380 DoWrite( &((*it).second), output, indent + 1);
382 Indent(output, indent);
383 if( value->GetType() == TreeNode::OBJECT )
401 case TreeNode::STRING:
403 output << "\"" << value->GetString() << "\"";
404 if(NULL != value->mNextSibling)
415 case TreeNode::INTEGER:
417 output << value->GetInteger();
418 if(NULL != value->mNextSibling)
429 case TreeNode::FLOAT:
431 output.setf( std::ios::floatfield );
432 output << value->GetFloat();
433 output.unsetf( std::ios::floatfield );
434 if(NULL != value->mNextSibling)
444 case TreeNode::BOOLEAN:
446 if( value->GetInteger() )
454 if(NULL != value->mNextSibling)
469 const TreeNode* FindIt(const std::string& childName, const TreeNode* node)
471 DALI_ASSERT_DEBUG(node);
473 const TreeNode* found = NULL;
477 if( NULL != (found = node->GetChild(childName)) )
483 for(TreeNode::ConstIterator iter = node->CBegin(); iter != node->CEnd(); ++iter)
485 if( NULL != (found = FindIt(childName, &((*iter).second)) ) )
495 char *CopyString( const char *fromString, VectorCharIter& iter, const VectorCharIter& sentinel)
497 DALI_ASSERT_DEBUG(fromString);
498 DALI_ASSERT_DEBUG(iter != sentinel);
500 char *start= &(*iter);
501 const char *ptr = fromString;
507 DALI_ASSERT_DEBUG(iter != sentinel);
517 } // namespace internal
519 } // namespace Toolkit